Skip to content

AuditEnvelope v1 — unified abstract audit message format (Phases B + C + F) #97

@hanwencheng

Description

@hanwencheng

Context

PR #95 (issue #82 ERC-7730 + EIP-712 sign) added signed_intent_text + signed_intent_hash to the audit-row schema, but only for typed-data signs. AuditEnvelope v1 is the canonical abstract format every audit-producing surface emits going forward.

Phase A — the canonical schema + non-break design — landed in PR #95 under arch.md §15.3a. This issue tracks the implementation phases B / C / F.

2026-06-11 sync to current design (checkbox audit against main @ b75597c): Phases B + C are fully shipped; Phase F's data-plane families (cred/memory/config) are live via #229 / PR #261. Deviations from the original plan are called out inline below. Remaining work: the control-plane emit sites (sign / scope / device — in progress), then email / K3 / payments / K10-rotate.

Phase B — worker + core migration ✅ SHIPPED

Phase C — contract revision ✅ SHIPPED (prod); test-stack redeploy pending

  • appendV2(operatorOmni, actorOmni, opKind, envelopeHash) in CredentialAudit.sol — additive, v1 retained. Design refinement: V2 is event-only (no on-chain entry/root storage; the indexed event log is the canonical history — entry position derivable from block number + log index).
  • appendRootV2(operatorOmni, merkleRoot, opKindBitmap, entryCount)opKindBitmap: bytes32, bit N = op_kind N; gated to the operator master wallet like V1 appendRoot. The audit worker queues V2 envelope hashes per operator and flush returns the appendRootV2 inputs (Worker-side durable audit for memory + cred data-plane ops (store/fetch) #229).
  • AuditAppendedV2 + AuditRootAppendedV2 events with indexed opKind topic.
  • Forge tests covering both shapes coexisting (AgentKeysV1.t.sol).
  • Heima Mainnet prod: live in the 0.3 contract set (deployed 2026-06-09 via heima-bring-up.sh). ⚠️ The CI/test stack's CredentialAudit predates the V2 surface — appendRootV2 anchors soft-skip there by design until its next contract-set redeploy (VERSION bump ceremony).
  • Contract registry updated — addresses live in the chain profile heima.json (contract_set_version 0.3); deployed-contracts.md carries the prose (the doc no longer holds an address table).

Phase F — extend op_kind coverage

All bytes were pre-claimed in the Phase A table, so the per-row work is: emit-site wiring + the 3-test ritual (arch.md row already exists).

Live (data plane, #229 / PR #261):

  • CredStore (0) + CredFetch (1) + CredTeardown (2) — credentials worker.
  • MemoryPut (10) + MemoryGet (11) + MemoryTeardown (12) — memory worker.
  • ConfigPut (80) + ConfigGet (81) + ConfigTeardown (82) — config worker (family 80–89 claimed via the §15.3b ritual; not in this issue's original table).

In progress (control plane — PR forthcoming from this issue):

Remaining (each a follow-up PR):

  • K10Rotate (52) — blocked: no runtime K10 rotation flow exists yet.
  • PaymentEscrowRedeem (30) + PaymentDirect (31) — blocked on the §15.5 payment-service worker.
  • EmailSend (60) + EmailReceive (61) — email-service worker emit (worker exists; wire AuditEmitter like Worker-side durable audit for memory + cred data-plane ops (store/fetch) #229).
  • K3EpochAdvance (70) — advanceEpoch() is operator-script-driven today; the emit site lands with whatever runtime component calls it.

Open design item (deferred from #229): audit-worker-initiated on-chain submission of appendRootV2 (tier-A relay). Today flush returns the inputs and the operator master submits (worker smoke + harness do this). True worker-initiated anchoring needs a master-delegated relay wallet or a contract-side allowance — design TBD here.

Non-break invariants (per arch.md §15.3a)

Unchanged — every PR landing a new op_kind MUST preserve all 8 invariants (open u8 enum, stable envelope-level fields, version gated on envelope-level breakage only, explorer Unknown(byte) fallback, opaque op_body passthrough, op-kind-agnostic contract, canonical table append-only in arch.md, 3 tests per op_kind).

Companion issue

Explorer-side work (phases D/E) tracked at litentry/subscan-essentials#12.

Acceptance

  • Phase B + C ship.
  • Phase F has ≥3 op_kinds wired end-to-end (9 data-plane op_kinds live with appendRootV2 batching, asserted by harness/v2-stage3-demo.sh steps 11-12 + heima-worker-smoke.sh).
  • The recommended control-plane trio (SignEip712, ScopeGrant, DeviceAdd) wired — in progress (see above).
  • Explorer renders the wired op_kinds; others render via the Unknown(byte) fallback (subscan-essentials#12).

Related: #82 (closed by #95), #90 (Stage 2 hardening), #91 (worker hardening), #201 (config data class), #229 (worker durable audit, PR #261).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/auditAudit worker, two-tier audit (off-chain feed + on-chain anchor)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions