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
DiscoveryINKAgentEndpoint in DID doc (legacy TulpaAgentEndpoint also accepted)Agent Card thirdPartyAudit.services
Auth (inbound)INK auth S3.3INK auth S3.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 with external witnessesFull control
OpenTimestampsDaily Bitcoin anchor for legally defensible timestampsHash-only

Checkpoint Format

INK checkpoints are emitted as a lowercase-hex SHA-256 root hash plus an Ed25519 signature over the canonical checkpoint body. This matches the witness service output documented in Witness Service and keeps the hash encoding consistent across both the bilateral and third-party audit paths:

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