Third-Party Audit
Bilateral audit exchange has a fundamental limitation: a malicious agent can maintain two different hash chains and show each counterparty a different history (split-view attack). Third-party audit services solve this by introducing an independent witness that neither party controls.
Architecture
Service Identity
A third-party audit service is a INK service role, not a standard INK agent:
| Concern | INK Agent | Audit Service |
|---|---|---|
| Identity | DID bound to human via agentLink | did:web or did:key — self-sovereign |
| Discovery | TulpaAgentEndpoint in DID doc | Agent Card thirdPartyAudit.services |
| Auth (inbound) | INK auth §3.3 | INK auth §3.3 (same) |
| Auth (outbound) | Signs with agentLink key | Signs with its own Ed25519 key |
| Delegation proof | Required | Not applicable — configured trust |
Submission Protocol
Agents submit events alongside normal hash chain maintenance. Submission is asynchronous and non-blocking.
POST /ink/v1/audit/submit
{ "protocol": "ink/0.1", "type": "network.tulpa.audit_submit", "from": "did:plc:agent", "to": "did:web:audit.example.com", "event": { /* InkAuditEvent */ }, "nonce": "<base64url>", "timestamp": "2026-03-19T12:00:00Z"}Signed Inclusion Receipt
{ "protocol": "ink/0.1", "type": "network.tulpa.audit_inclusion", "eventId": "01JBTEST0001", "treeSize": 48291, "leafIndex": 48290, "rootHash": "<SHA-256 hex of Merkle tree root>", "timestamp": "2026-03-19T12:00:01Z", "serviceSignature": "<Ed25519 over (eventId + treeSize + rootHash + timestamp)>"}Submission + Inclusion Flow (Detailed)
What happens step-by-step when an agent submits an event to a third-party audit service.
Access Control
The service operates under access-controlled transparency (per SCITT):
- Events are tagged with
messageIdand sender/recipient DIDs - Only parties to a message (or holders of a valid delegation chain) can query
- The Merkle tree structure is public; event contents are access-controlled
Merkle Tree Structure
Trust Model
The audit service is a semi-trusted witness, not an arbiter:
- It CANNOT forge events (Ed25519 signatures from agents)
- It CANNOT modify events without breaking Merkle proofs
- It CAN suppress events (detectable via consistency proofs)
- It CAN be unavailable (agents fall back to bilateral exchange)
For high-stakes interactions, agents MAY submit to multiple independent services.
Agent Card Advertisement
{ "capabilities": { "auditExchange": true, "thirdPartyAudit": { "services": [ { "endpoint": "https://audit.example.com/ink/v1", "did": "did:web:audit.example.com", "publicKey": "<Ed25519 public key hex>" } ], "submitPolicy": "all" } }}submitPolicy: all | high_value | none
Implementation Tiers
Tier 1 — Lowest effort, highest immediate value
| Approach | How it works | Privacy |
|---|---|---|
Witness cosigning (C2SP tlog-witness) | Periodic checkpoints, independent witnesses verify consistency | Witnesses see only tree size + root hash |
| Rekor hash notary (Sigstore) | Submit checkpoint hashes to Rekor’s public log | Hash-only — content stays private |
Tier 2 — Medium effort, stronger guarantees
| Approach | How it works | Privacy |
|---|---|---|
| SCITT service | COSE_Sign1-wrapped events, Merkle inclusion receipts | Access-controlled |
| INK-native Merkle service | INK auth, INK message format | Full INK access control |
Tier 3 — Infrastructure investment
| Approach | How it works | Privacy |
|---|---|---|
| Tessera-based log | Static tile serving (S3/R2) with external witnesses | Full control |
| OpenTimestamps | Daily Bitcoin anchor for legally defensible timestamps | Hash-only |
Checkpoint Format
INK checkpoints follow the C2SP tlog-checkpoint format:
ink-audit/<agentDid><sequence number><base64 root hash>
<Ed25519 note signature>