Skip to content

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

Diagram

Service Identity

A third-party audit service is a INK service role, not a standard INK agent:

ConcernINK AgentAudit Service
IdentityDID bound to human via agentLinkdid:web or did:key — self-sovereign
DiscoveryTulpaAgentEndpoint in DID docAgent Card thirdPartyAudit.services
Auth (inbound)INK auth §3.3INK auth §3.3 (same)
Auth (outbound)Signs with agentLink keySigns with its own Ed25519 key
Delegation proofRequiredNot 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.

Diagram

Access Control

The service operates under access-controlled transparency (per SCITT):

  • Events are tagged with messageId and 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

Diagram

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

ApproachHow it worksPrivacy
Witness cosigning (C2SP tlog-witness)Periodic checkpoints, independent witnesses verify consistencyWitnesses see only tree size + root hash
Rekor hash notary (Sigstore)Submit checkpoint hashes to Rekor’s public logHash-only — content stays private

Tier 2 — Medium effort, stronger guarantees

ApproachHow it worksPrivacy
SCITT serviceCOSE_Sign1-wrapped events, Merkle inclusion receiptsAccess-controlled
INK-native Merkle serviceINK auth, INK message formatFull INK access control

Tier 3 — Infrastructure investment

ApproachHow it worksPrivacy
Tessera-based logStatic tile serving (S3/R2) with external witnessesFull control
OpenTimestampsDaily Bitcoin anchor for legally defensible timestampsHash-only

Checkpoint Format

INK checkpoints follow the C2SP tlog-checkpoint format:

ink-audit/<agentDid>
<sequence number>
<base64 root hash>
<Ed25519 note signature>