Skip to content

v0.1.0-alpha.3

Pre-release
Pre-release

Choose a tag to compare

@jasonodoom jasonodoom released this 01 Jun 17:31
· 113 commits to main since this release
v0.1.0-alpha.3
45077b7

Closes the last HIGH conformance-audit finding (witness audit-query
response missing signature, proofs and protocol envelope).

Added

  • signAuditQueryResponse(payload, privateKey) and verifyAuditQueryResponseSignature(payload, signature, publicKey) primitives. Canonical signed bytes are ink/audit-query-response/v1\n + JCS(payload without serviceSignature). The payload binds serviceDid, messageId, requester, events, proofs, treeSize, rootHash, timestamp, so a valid signature cannot be rebound to a different witness, message, requester, or root.
  • verifyAuditQueryResponse({response, witnessPublicKey, expectedRequester, expectedMessageId, verifyEventSignature, expectedServiceDid?, laterCheckpoint?}) is the recommended high-level verifier. verifyEventSignature is a REQUIRED callback that resolves the submitting agent's keys and validates each event's agentSignature. Without it, the verifier refuses to return valid, because Merkle inclusion alone does not prove agent provenance (§7.5). The function enforces envelope shape, requester binding, events/proofs strict one-to-one alignment, the §7.4 per-event scope rule, walks every Merkle proof via computeAuditMerkleLeafHash up to the response's rootHash, runs verifyEventSignature on every event and supports optional later-checkpoint cross-check. verifyAuditQueryResponseSignature alone is signature-only and is documented as a low-level primitive.
  • computeAuditMerkleLeafHash(event) primitive: the RFC 6962 leaf-hash rule for inclusion proofs, SHA-256(0x00 || JCS(event-without-agentSignature)). Distinct from computeEventHash (unprefixed, used only for previousEventHash chain linkage). Verifiers walking an inclusion proof MUST use this function, not computeEventHash.
  • Nix flake now exposes apps.default, so nix run github:Ad-Astra-Computing/ink -- verify-inclusion --file r.json --witness URL works without npm install.

Security

  • The §7.3 envelope now binds requester. Without this binding, a signed witness response generated for Alice could be replayed to Bob as Bob's authoritative view of the same messageId. Verifiers MUST check the response's requester equals their locally authenticated requester before accepting events as a complete view.
  • Witnesses MUST fail closed when the requester's visible event set for a messageId exceeds the response cap, returning an unsigned HTTP 413 rather than silently signing a partial response. The reference and OSS witnesses query LIMIT MAX_QUERY_EVENTS + 1, detect overflow and refuse to sign.
  • Witnesses MUST emit a deterministic, stable result-set order so signed bytes are reproducible. The reference and OSS witnesses use ORDER BY event_id ASC.
  • Storage-integrity failures during proof construction (missing event_hash, hash mismatch, missing Merkle node, unprovable leaf, malformed event_json) now return HTTP 500 instead of silently omitting events from a signed response.
  • All canonicalize-and-sign / canonicalize-and-verify paths now cap by UTF-8 byte length, not JS string length. With non-ASCII event data the prior cap could be undercounted and let oversized payloads through. Affects buildSignatureBase, computeMessageHash, signAuditEvent / verifyAuditEventSignature, computeEventHash, signAuditResponse / verifyAuditResponseSignature, signAuditQueryResponse / verifyAuditQueryResponseSignature and the witness handleQuery response-size guard.
  • verifyAuditEventSignature, verifyAuditResponseSignature, verifyAuditQueryResponseSignature now wrap canonicalization inside the try/catch, so payloads that pass the complexity precheck but throw inside jcsCanonicalize (e.g. objects with undefined values) return false instead of propagating.

Spec

  • specs/ink-auditability.md §7.3 (audit-query response) now defines the full signed-envelope shape: {protocol, type: "network.tulpa.audit_query_response", serviceDid, messageId, requester, events, proofs[{eventId, leafIndex, inclusionProof}], treeSize, rootHash, timestamp, serviceSignature}. Previous text described a bare {events} shape with no signature, no protocol envelope and no per-event proofs.
  • §7.3 leaf-hash text now references computeAuditMerkleLeafHash directly and warns implementers that computeEventHash (chain linkage) is NOT the leaf input.
  • §7.3 now explicitly forbids witnesses from signing partial results: truncation MUST be an unsigned error. A signed response is a complete enumeration of the requester's visible events at (treeSize, rootHash).
  • §7.3 requires witnesses to emit events and proofs in a stable, deterministic order.