diff --git a/crypto/FLOWCHAIN_LOCAL_ALPHA_OBJECTS.md b/crypto/FLOWCHAIN_LOCAL_ALPHA_OBJECTS.md new file mode 100644 index 00000000..a82f207a --- /dev/null +++ b/crypto/FLOWCHAIN_LOCAL_ALPHA_OBJECTS.md @@ -0,0 +1,248 @@ +# FlowChain Local Alpha Object Identity + +Status: local/test V0. + +This document defines the canonical cryptographic IDs for the FlowChain Local +Alpha object model. These IDs are the crypto package boundary that devnet, +control-plane, API, verifier, and dashboard agents should consume. Do not invent +alternate hash formats for these objects. + +## RD Crypto Boundary + +The user noted that the RD library is for cryptography. I inspected this +workspace and nearby `E:\FlowMemory` research paths. + +No RD-named cryptography library exists inside this worktree. The current +authoritative FlowMemory crypto package is: + +```text +E:\FlowMemory\flowmemory-crypto\crypto +``` + +Nearby research/RD crypto sources do exist: + +```text +E:\FlowMemory\github-research-sources\noesis-l1\crates\noesis-crypto +E:\FlowMemory\github-research-sources\noesis-l1\crates\noesis-zk +E:\FlowMemory\github-research-sources\noesis-l1\crates\flowchain-pw +E:\FlowMemory\github-research-sources\FlowMemory-2026-05-11\projects\noesis-l1\crates\noesis-crypto +``` + +Those crates are useful RD references for object vocabulary, future proof +interfaces, and Process-Witness research. They are not consumed directly by this +package because the current `noesis-crypto` crate uses SHA-256 prototype object +hashes, and `noesis-zk` explicitly marks production proof systems and +commitment schemes as scaffolded. FlowChain Local Alpha IDs use the existing +FlowMemory rule: + +```text +keccak256(abi.encode(TYPEHASH, field_1, field_2, ...)) +TYPEHASH = keccak256(bytes(type_string)) +``` + +FlowChain should consume the nearby RD libraries as research inputs only until a +separate compatibility issue accepts a cross-language adapter and vectors that +match the Keccak typed hashes in this package. + +## Object IDs + +All object IDs are bytes32 Keccak typed hashes. Variable-length names, policy +documents, manifests, source code, response bodies, and dependency sets must be +pre-hashed before entering the typed object. + +| Object | ID field | Type string key | Domain string key | Helper | +| --- | --- | --- | --- | --- | +| AgentAccount | `agentId` | `agentAccountV0` | `agentAccountId` | `agentAccountId` | +| ModelPassport | `modelId` | `modelPassportV0` | `modelPassportId` | `modelPassportId` | +| WorkReceipt | `workReceiptId` | `workReceiptV0` | `workReceiptId` | `workReceiptId` | +| ArtifactAvailabilityProof | `proofId` | `artifactAvailabilityProofV0` | `artifactAvailabilityProofId` | `artifactAvailabilityProofId` | +| VerifierModule | `moduleId` | `verifierModuleV0` | `verifierModuleId` | `verifierModuleId` | +| VerifierReport | `reportId` | `verifierReportV0` | `verifierReportDigest` | `verifierReportHash` | +| MemoryCell | `memoryCellId` | `memoryCellV0` | `memoryCellId` | `memoryCellId` | +| Challenge | `challengeId` | `challengeV0` | `challengeId` | `challengeId` | +| FinalityReceipt | `finalityReceiptId` | `finalityReceiptV0` | `finalityReceiptId` | `finalityReceiptId` | +| HardwareSignalEnvelope | `hardwareSignalEnvelopeId` | `hardwareSignalEnvelopeV0` | `hardwareSignalEnvelopeId` | `hardwareSignalEnvelopeId` | +| Control-plane provenance response | `provenanceResponseId` | `controlPlaneProvenanceResponseV0` | `controlPlaneProvenanceResponseId` | `controlPlaneProvenanceResponseId` | + +`WorkReceipt` and `VerifierReport` intentionally reuse the existing +FlowMemory V0 domains, `flowmemory.v0.work.receipt-id` and +`flowmemory.v0.verifier.report-digest`. The other Local Alpha object domains +use `flowchain.local-alpha.v0.*`. This keeps the local testnet vocabulary +compatible with the existing receipt/report package instead of creating a +second receipt/report identity system. + +`LocalSignatureEnvelope` uses `localSignatureEnvelopeV0` and +`localSignatureEnvelopeHash`. It signs the object ID, object schema hash, +domain separator, signer ID, signer key ID, signer role, sequence, validity +window, and nonce. The signing digest is the local EIP-712 style digest over +that struct hash and the object domain separator. + +Runnable definitions live in `crypto/src/objects.js`. + +Canonical object fixtures live in: + +```text +crypto/fixtures/local-alpha-objects.json +``` + +Package-level vectors are pinned in: + +```text +crypto/fixtures/vectors.json +``` + +The Local Alpha JSON Schemas live in: + +```text +schemas/flowmemory/agent-account.schema.json +schemas/flowmemory/model-passport.schema.json +schemas/flowmemory/work-receipt.schema.json +schemas/flowmemory/memory-cell.schema.json +schemas/flowmemory/artifact-availability-proof.schema.json +schemas/flowmemory/verifier-module.schema.json +schemas/flowmemory/verifier-report.schema.json +schemas/flowmemory/challenge.schema.json +schemas/flowmemory/finality-receipt.schema.json +schemas/flowmemory/hardware-signal-envelope.schema.json +schemas/flowmemory/local-signature-envelope.schema.json +schemas/flowmemory/control-plane-provenance-response.schema.json +``` + +## Local Signature Envelope Rules + +Local Alpha accepts four signer roles: + +| Role | Intended signer | Boundary | +| --- | --- | --- | +| `operator` | local operator process or operator-vault adapter | No value-bearing wallet claim. The fixture keys are deterministic no-value test keys. | +| `agent` | registered `AgentAccount` local key | Signs local work receipts, memory cells, challenges, or agent-scoped provenance. | +| `verifier` | local verifier module/report signer | Signs verifier modules, verifier reports, and finality receipts as testnet statements, not trustless proofs. | +| `hardware` | FlowRouter or simulator device key | Signs low-bandwidth control envelopes only. Heavy payloads remain off-chain. | + +Envelope validation requires: + +- `objectSchema`, `objectType`, and `objectTypeHash` match the document schema. +- `objectId` matches the recomputed document ID. +- `domain` and `domainSeparator` match the canonical object domain. +- `signerId`, `signerKeyId`, `publicKey`, and `signature` are present. +- signer role is allowed for the object type. +- `envelopeId` and `signingDigest` recompute from the envelope fields. +- the secp256k1 signature verifies against the signing digest and public key. +- the caller supplies replay context and rejects repeated signer/domain/sequence tuples. +- critical object hashes are nonzero, dependency roots are well-formed, parent/root relationships are coherent, and the object type is not swapped. + +The fixture validator covers invalid vectors for replay, wrong domain, missing +signer, bad signature, zero hash, malformed ID, malformed dependency, bad +parent/root, and wrong object type. Every Local Alpha object envelope also has a +valid fixture and a bad-signature invalid fixture. + +## Consumer Rules + +Chain/devnet: + +- Use these IDs as local transaction/object keys. +- Reject malformed IDs, zero critical roots, bad parent/root transitions, + wrong object types, and replayed signer/domain/sequence tuples before state + mutation. +- Do not treat signatures as production wallet custody or value-bearing + authorization. + +Services/control plane: + +- Import the crypto package or reproduce the type strings and vectors exactly. +- Run `validateLocalAlphaEnvelope` before accepting local object documents from + transactions, APIs, fixtures, or hardware packets. +- Store validation errors explicitly instead of silently coercing objects. + +Dashboard/workbench: + +- Display object IDs, domains, signer role, status label, and validation errors. +- Show verifier reports and finality receipts as local/test statements unless a + later proof/enforcement path is accepted. + +Hardware: + +- Use `HardwareSignalEnvelope` for compact control signals only. +- Treat LoRa and Meshtastic fields as low-bandwidth control provenance, not as + artifact transport or internet replacement. +- Keep raw hardware payloads off-chain and bind them through `signalRoot`. + +## What V0 Proves + +V0 proves deterministic identity and tamper-evident binding for the typed fields +included in each object ID. If any included field changes, the ID changes. + +V0 also proves: + +- field-order compatibility with the FlowMemory Keccak ABI typed-hash rule; +- domain/type-string separation for each object class; +- malformed hex rejection for bytes32/address fields; +- canonical JSON stability for pre-hashed control-plane response bodies; +- duplicate ID detection in fixture validation; +- explicit finality and challenge state labels for local/test consumers. + +## What V0 Does Not Prove + +V0 does not prove that an AI model output is correct, that a verifier is honest, +that storage remains available forever, that hidden dependencies are complete, +or that a challenge outcome is economically secure. + +V0 does not implement production proof circuits, GPU proofs, verifier +economics, encrypted compute, production consensus, or a public L1. The object +IDs are stable commitments and provenance handles, not a trustless proof system. + +## Explicit RD Gates + +These tracks are gated and must not be treated as implemented by this package: + +- Process-Witness: research input only until public inputs, witness format, + replay policy, privacy boundaries, and cross-language vectors are accepted. +- SEAL/dependency privacy: attach through `dependencyRoot` and challenge roots + only until dependency atom schemas, disclosure policy, and verifier checks are + accepted. +- Synthetic Non-Amplification: no claims until there is a formal rule, fixture + corpus, verifier module, and dashboard/status vocabulary. +- Advanced encrypted compute: no runtime or security claim until threat model, + key lifecycle, leakage policy, and deterministic verifier boundary exist. +- GPU proofs: no proof claim until proof system, public inputs, cost model, + verifier module, and reproducible local vectors exist. +- Audited production proof systems: no audit or production-readiness claim until + a named audit artifact, issue/decision record, and enforcement path are merged. + +## Dependency And SEAL Mapping + +The Local Alpha object model leaves a forward-compatible slot for future SEAL or +dependency-atom work: + +- `MemoryCell.dependencyRoot` commits to the dependency atoms or dependency + certificate set that a memory update relies on. +- `ControlPlaneProvenanceResponse.dependencyRoot` lets an API response cite the + same dependency state without embedding private dependency atoms. +- `Challenge.challengeType = dependency_omission` gives omitted-dependency + challenges a canonical local/test object ID. +- `VerifierModule.supportedChallengeTypesRoot` and `supportedModesRoot` can + commit to future verifier support for SEAL, dependency separation, or + completeness checks. +- `FinalityReceipt.challengeRoot` keeps finality downgradeable if a later + dependency challenge succeeds. + +Future SEAL objects should hash their own public inputs into roots and attach +through these fields. They should not mutate the V0 object ID type strings. + +## Future Proof-Carrying Receipts + +Proof-carrying receipts can be added without breaking V0 IDs by treating proofs +as new linked objects rather than new bytes inside existing ID preimages. + +The stable path is: + +1. Keep V0 IDs unchanged. +2. Define a new proof object with its own schema, type string, public inputs, + proof system id, verifier module id, and proof artifact commitment. +3. Link that proof object to `receiptId`, `reportId`, `challengeId`, + `finalityReceiptId`, or `dependencyRoot`. +4. If a breaking receipt hash is needed later, create a V1 type string instead + of changing V0. + +This lets Local Alpha dashboards and APIs rely on V0 IDs while future proof +systems attach stronger evidence as additional commitments. diff --git a/crypto/FLOWMEMORY_CRYPTO_SPEC.md b/crypto/FLOWMEMORY_CRYPTO_SPEC.md index 4ba48d15..44b23c46 100644 --- a/crypto/FLOWMEMORY_CRYPTO_SPEC.md +++ b/crypto/FLOWMEMORY_CRYPTO_SPEC.md @@ -103,6 +103,16 @@ verifierIdentity merkleLeaf merkleInternalNode devnetBlockHash +agentAccountId +modelPassportId +memoryCellId +artifactAvailabilityProofId +verifierModuleId +challengeId +finalityReceiptId +hardwareSignalEnvelopeId +controlPlaneProvenanceResponseId +localSignatureEnvelope ``` ## Versioning Strategy @@ -128,6 +138,8 @@ The current package implements: - deterministic verifier reports - verifier signature envelopes - reorg-aware status handling +- FlowChain Local Alpha object identity for agent accounts, model passports, work receipts, artifact availability proofs, verifier modules, verifier reports, memory cells, challenges, finality receipts, hardware signal envelopes, and control-plane provenance responses +- Local Alpha operator, agent, verifier, and hardware signature envelope payloads and validators for replay, wrong domain, missing signer, zero hash, malformed id, malformed dependency, bad parent/root, and wrong object type checks - test vectors and cross-language conformance tests The runnable package in `crypto/src/` currently implements the v0 hash utilities and tests them against fixtures in `crypto/fixtures/`. @@ -139,6 +151,7 @@ MVP should remain verifier-attested for: - storage provider claims - model or worker behavior - final status labels before proof systems exist +- local operator-vault policy; current fixture keys are deterministic no-value test keys and do not represent wallet custody, production account control, or transferable value ## Future Split @@ -176,3 +189,4 @@ Searches for `Claw` and `claw` in repository issues and code returned no matchin - Define key registry and verifier set root governance. - Define challenge evidence and response envelopes. - Produce a decision record before CursorRegistry or proof-carrying receipts are implemented. +- Decide when, if ever, the nearby Noesis/FlowChain RD crypto crates should receive a Keccak compatibility adapter for these V0 object IDs. diff --git a/crypto/README.md b/crypto/README.md index 54ae3b69..93cd96ea 100644 --- a/crypto/README.md +++ b/crypto/README.md @@ -33,6 +33,13 @@ Validate all package-level vector fixtures: npm run validate:vectors ``` +Validate the Local Alpha object and signature-envelope fixtures against the +canonical JSON Schemas: + +```powershell +npm run validate:local-alpha +``` + ## Read Order 1. `FLOWMEMORY_CRYPTO_SPEC.md` @@ -40,9 +47,10 @@ npm run validate:vectors 3. `RECEIPT_HASHING.md` 4. `MERKLE_AND_ROOTS.md` 5. `ATTESTATIONS.md` -6. `TEST_VECTORS.md` +6. `FLOWCHAIN_LOCAL_ALPHA_OBJECTS.md` +7. `TEST_VECTORS.md` -Runnable fixtures live in `fixtures/`. `fixtures/vectors.json` contains the current 21 package-level vectors. Supporting cross-language vectors live in `test-vectors/`. +Runnable fixtures live in `fixtures/`. `fixtures/vectors.json` contains the current 33 package-level vectors. `fixtures/local-alpha-objects.json` contains positive and negative Local Alpha object and signed-envelope fixtures. Supporting cross-language vectors live in `test-vectors/`. Validate the current vector set with: @@ -50,7 +58,7 @@ Validate the current vector set with: python validate_test_vectors.py ``` -The Python validator is a cross-check for the FlowPulse aggregate vector. The production-candidate package paths are `npm test` and `npm run validate:vectors`. +The Python validator is a cross-check for the FlowPulse aggregate vector. The primary local/test package paths are `npm test`, `npm run validate:vectors`, and `npm run validate:local-alpha`. ## Core Vocabulary @@ -60,10 +68,12 @@ The Python validator is a cross-check for the FlowPulse aggregate vector. The pr - `artifactRoot`: commitment to off-chain artifact bytes and metadata. - `reportId`: deterministic identifier for a verifier report. - `attestation`: signed worker or verifier envelope over a receipt, report, artifact, or root. +- Local Alpha object IDs: canonical IDs for `AgentAccount`, `ModelPassport`, `WorkReceipt`, `ArtifactAvailabilityProof`, `VerifierModule`, `VerifierReport`, `MemoryCell`, `Challenge`, `FinalityReceipt`, hardware signal envelopes, and control-plane provenance responses. +- Local Alpha signature envelopes: local operator, agent, verifier, and hardware secp256k1 test signatures over typed object IDs. These are no-value local/test keys and are not wallet custody or production key-management claims. ## Implemented Helpers -The package exports Keccak helpers, canonical JSON hashing, typed hash utilities, FlowPulse observation ids, cursor ids, report digests, receipt hashes, artifact/root commitments, work receipt ids, Merkle roots, worker/verifier signature payloads, verifier attestation envelope hashes, and local secp256k1 sign/verify helpers for tests. +The package exports Keccak helpers, canonical JSON hashing, typed hash utilities, FlowPulse observation ids, cursor ids, report digests, receipt hashes, artifact/root commitments, work receipt ids, Local Alpha object ids, hardware signal envelope ids, Local Alpha signature envelope payloads, envelope validators, Merkle roots, worker/verifier signature payloads, verifier attestation envelope hashes, and local secp256k1 sign/verify helpers for tests. The implementation is ESM JavaScript with `src/index.d.ts` declarations for TypeScript consumers. @@ -77,9 +87,18 @@ Future work may add proof-carrying receipts, zk circuits for receipt consistency ## Integration Notes -There is no `services/shared/` package in this repository yet. Until one exists, services should either: +There is a fixture-first `services/shared/` package in this repository, but the crypto package remains the authoritative source for the hash formats in this directory. Services should either: - import this package directly from `crypto/` in local development, or - mirror the exported functions from `crypto/src/index.js` with tests against `crypto/fixtures/`. Indexer and verifier services must not hand-roll different hash formats. If a service cannot import this package, it should copy the type strings and vectors exactly and prove compatibility by passing the same fixture hashes. + +Nearby Noesis/FlowChain RD crates under `E:\FlowMemory\github-research-sources\noesis-l1\crates\` are research inputs only for this package. They should not replace these Keccak typed-hash vectors unless a compatibility adapter and matching cross-language vectors are accepted. + +## Downstream Consumption + +- Chain/devnet agents should use the object ID helpers as transaction/object keys and reject zero roots, malformed IDs, wrong object types, replayed signer sequences, and bad parent/root relationships before state updates. +- Services and verifiers should use `validateLocalAlphaEnvelope` before accepting object documents from local transactions, API calls, hardware packets, or fixture imports. +- Dashboard/workbench agents should display IDs, domains, signer roles, status labels, and validation errors from these fixtures without implying production proof security. +- Hardware agents should treat hardware signal envelopes as low-bandwidth authenticated control messages only; payloads remain off-chain and signal roots are commitments, not radio bandwidth or field-deployment claims. diff --git a/crypto/TEST_VECTORS.md b/crypto/TEST_VECTORS.md index bed19b28..38907e32 100644 --- a/crypto/TEST_VECTORS.md +++ b/crypto/TEST_VECTORS.md @@ -9,7 +9,8 @@ The test vectors are synthetic and contain no production secrets or signatures. - `fixtures/sample-flowpulse.json`: FlowPulse event args and expected `pulseId` / `eventArgsHash`. - `fixtures/sample-observation.json`: observation metadata, artifact/storage inputs, and expected `observationId` / `receiptHash`. - `fixtures/sample-report.json`: verifier report, worker signature payload, verifier signature payload, and attestation envelope expectations. -- `fixtures/vectors.json`: 21 package-level vectors for domains, canonical JSON, observation ids, receipts, artifacts, Merkle roots, reports, attestations, cursors, identities, root commitments, work receipts, and devnet block hashes. +- `fixtures/local-alpha-objects.json`: positive and negative fixtures for FlowChain Local Alpha object identity, signed-envelope validation, and schema validation. +- `fixtures/vectors.json`: 33 package-level vectors for domains, canonical JSON, observation ids, receipts, artifacts, Merkle roots, reports, attestations, cursors, identities, root commitments, work receipts, devnet block hashes, Local Alpha object ids, hardware signal envelopes, and local signature envelopes. - `test-vectors/flowpulse-observation-v0.json`: FlowPulse-specific observation, receipt, artifact, report, worker signature digest, and verifier signature digest. ## FlowPulse Observation Vector Highlights @@ -49,6 +50,8 @@ An implementation should reproduce: - Merkle root and artifact root - deterministic verifier report id - EIP-712 signing digests without requiring test private keys +- Local Alpha object IDs for AgentAccount, ModelPassport, WorkReceipt, ArtifactAvailabilityProof, VerifierModule, VerifierReport, MemoryCell, Challenge, FinalityReceipt, hardware signal envelopes, and control-plane provenance responses +- Local Alpha signature envelope IDs and signing digests for local operator, agent, verifier, and hardware no-value test keys Run the package test suite: @@ -66,7 +69,20 @@ npm run validate:vectors Expected output: ```text -FLOWMEMORY_CRYPTO_VECTORS_OK 21 +FLOWMEMORY_CRYPTO_VECTORS_OK 33 +``` + +Validate the Local Alpha object documents and signature envelopes against the +canonical JSON Schemas: + +```powershell +npm run validate:local-alpha +``` + +Expected output: + +```text +FLOWCHAIN_LOCAL_ALPHA_FIXTURES_OK documents=11 envelopes=11 schemas=12 ``` Print the sample vector summary: @@ -94,7 +110,17 @@ FLOWPULSE_VECTOR_RECOMPUTE_OK - changed `uri` should change `eventArgsHash` - swapped Merkle leaves should change `contentMerkleRoot` and therefore any recomputed `artifactRoot` - wrong verifier set root should change verifier signing digest +- swapped Local Alpha object fields should change object IDs +- changed Local Alpha type/domain strings should change object IDs or domain separators +- malformed hex in Local Alpha fixtures should fail before an ID is accepted +- duplicate Local Alpha object IDs should be rejected by fixture validation +- canonical JSON key order should not change the control-plane provenance response body hash +- replayed Local Alpha signer/domain/sequence tuples should be rejected +- wrong signature domains should be rejected +- missing local operator/agent/verifier/hardware signer fields should be rejected +- each Local Alpha object envelope has a bad-signature invalid vector +- zero critical hashes, malformed object IDs, malformed dependency roots, bad parent/root relationships, and wrong object types should be rejected - expired worker signature should be rejected by verifier policy - reorged observation should not mutate into a verified report -The package tests cover the first five checks. Expiry and reorg-to-report policy are verifier-service responsibilities because they require policy context, not just hash recomputation. +The package tests cover the hash, schema, malformed hex, duplicate, type-string, canonical JSON, signed-envelope, replay, wrong-domain, missing-signer, bad-signature, zero-hash, malformed-dependency, bad-parent/root, and wrong-object-type checks. Expiry and reorg-to-report policy are verifier-service responsibilities because they require policy context, not just hash recomputation. diff --git a/crypto/fixtures/local-alpha-objects.json b/crypto/fixtures/local-alpha-objects.json new file mode 100644 index 00000000..77735f8e --- /dev/null +++ b/crypto/fixtures/local-alpha-objects.json @@ -0,0 +1,1163 @@ +{ + "schema": "flowmemory.crypto.local-alpha-object-fixtures.v0", + "rdBoundary": { + "currentPackage": "E:\\FlowMemory\\flowmemory-crypto\\crypto", + "researchCryptoCrate": "E:\\FlowMemory\\github-research-sources\\noesis-l1\\crates\\noesis-crypto", + "researchZkCrate": "E:\\FlowMemory\\github-research-sources\\noesis-l1\\crates\\noesis-zk", + "consumeAs": "Research vocabulary and future proof input reference only. FlowChain Local Alpha object IDs are Keccak ABI typed hashes from this package.", + "operatorVaultBoundary": "Local Alpha signing keys are deterministic no-value test keys. Operator vault policy is a boundary document, not a wallet custody or value-bearing claim." + }, + "signingKeys": { + "operator": { + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "note": "Deterministic no-value local test key. Do not fund or reuse outside fixtures." + }, + "agent": { + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "note": "Deterministic no-value local test key. Do not fund or reuse outside fixtures." + }, + "verifier": { + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "publicKey": "0x02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "note": "Deterministic no-value local test key. Do not fund or reuse outside fixtures." + }, + "hardware": { + "signerId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signerKeyId": "0x2960db74c119e17ca2323f749c1df8bfdb1b7e5eaddf640d52fda9d96b59c61b", + "publicKey": "0x02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "note": "Deterministic no-value local test key. Do not fund or reuse outside fixtures." + } + }, + "positive": [ + { + "name": "agent-account.demo", + "schemaPath": "../../schemas/flowmemory/agent-account.schema.json", + "function": "agentAccountId", + "idField": "agentId", + "input": { + "namespaceId": "0x4c2eae268c3f97a510b66597873c6c08ae9e427a7c03cd383df6acfeda9bbf37", + "owner": "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1", + "policyRoot": "0x20121b5daa2be4de0d9dbcae292d1d3466a4e0a8b6cc3149ce46c30c352a1f0e", + "toolPermissionsRoot": "0x39079bde86c6743c81fd927a14012331688374b55118484529ce257317327120", + "modelAllowlistRoot": "0x00a463537f12e3419d4bf3655d28d93f3e189b9a89a3ad40c4819bbc4eb2acc9", + "memoryNamespaceRoot": "0x574eee506454973fb82863a3225ea78696b96907a17c360ad2c2b5234dfa2d83", + "spendingLimitPerEpoch": "0", + "nonce": "0x37e916697be966b19c0cd7aa6073e78ffb7ee5cf27a4392383f9cfe5fa5025bb" + }, + "expected": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "document": { + "schema": "flowchain.agent_account.v0", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "namespaceId": "0x4c2eae268c3f97a510b66597873c6c08ae9e427a7c03cd383df6acfeda9bbf37", + "owner": "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1", + "policyRoot": "0x20121b5daa2be4de0d9dbcae292d1d3466a4e0a8b6cc3149ce46c30c352a1f0e", + "toolPermissionsRoot": "0x39079bde86c6743c81fd927a14012331688374b55118484529ce257317327120", + "modelAllowlistRoot": "0x00a463537f12e3419d4bf3655d28d93f3e189b9a89a3ad40c4819bbc4eb2acc9", + "memoryNamespaceRoot": "0x574eee506454973fb82863a3225ea78696b96907a17c360ad2c2b5234dfa2d83", + "spendingLimitPerEpoch": "0", + "status": "active", + "nonce": "0x37e916697be966b19c0cd7aa6073e78ffb7ee5cf27a4392383f9cfe5fa5025bb" + } + }, + { + "name": "model-passport.demo", + "schemaPath": "../../schemas/flowmemory/model-passport.schema.json", + "function": "modelPassportId", + "idField": "modelId", + "input": { + "providerHash": "0x1dcd953776be1cde4f3d9f516d8ecf3641d664d8c97623af60327315c5600d0a", + "modelFamilyHash": "0x91c830851e70677b8aa487b104e05230fdd5d2ae5ee26b5423ca223b154b58cc", + "versionHash": "0x7c56a7f2edbd518ffcf014b4155ec4ad47062390e3a1302550e5a080c5ef4975", + "licenseRoot": "0x7c4f5757bbcb3cb1c84df192e87f2ba40b9d4cacb1e62b612e604a8d831bc4ee", + "policyRoot": "0x519cc6db7ebafcfa1add95a09f9ef811013d86d3e76e1d4b5099f9a379a98bdb", + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "metadataHash": "0x198ae9ec53443e3a46f8762e4b9ee166c2927d7faec07ce2bdc8714859504d17", + "nonce": "0x6550e26ef27367750192911d54ae8c97af6f828e52f4b696a25f215581a34b6b" + }, + "expected": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879", + "document": { + "schema": "flowchain.model_passport.v0", + "modelId": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879", + "providerHash": "0x1dcd953776be1cde4f3d9f516d8ecf3641d664d8c97623af60327315c5600d0a", + "modelFamilyHash": "0x91c830851e70677b8aa487b104e05230fdd5d2ae5ee26b5423ca223b154b58cc", + "versionHash": "0x7c56a7f2edbd518ffcf014b4155ec4ad47062390e3a1302550e5a080c5ef4975", + "licenseRoot": "0x7c4f5757bbcb3cb1c84df192e87f2ba40b9d4cacb1e62b612e604a8d831bc4ee", + "policyRoot": "0x519cc6db7ebafcfa1add95a09f9ef811013d86d3e76e1d4b5099f9a379a98bdb", + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "metadataHash": "0x198ae9ec53443e3a46f8762e4b9ee166c2927d7faec07ce2bdc8714859504d17", + "status": "active", + "nonce": "0x6550e26ef27367750192911d54ae8c97af6f828e52f4b696a25f215581a34b6b" + } + }, + { + "name": "work-receipt.demo", + "schemaPath": "../../schemas/flowmemory/work-receipt.schema.json", + "function": "workReceiptId", + "idField": "workReceiptId", + "input": { + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "workerId": "0x7803fe537f4b6e4ddd47f00b97a87c06aad1e42e22b83fdb522268e393319598", + "workerSequence": "1", + "nonce": "0x3574313751905cc45384e0a3f62258d38e9c64735e29bcee180459bb16cd4039" + }, + "expected": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9", + "document": { + "schema": "flowchain.work_receipt.v0", + "workReceiptId": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9", + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "workerId": "0x7803fe537f4b6e4ddd47f00b97a87c06aad1e42e22b83fdb522268e393319598", + "workerSequence": "1", + "status": "verified", + "nonce": "0x3574313751905cc45384e0a3f62258d38e9c64735e29bcee180459bb16cd4039" + } + }, + { + "name": "artifact-availability-proof.demo", + "schemaPath": "../../schemas/flowmemory/artifact-availability-proof.schema.json", + "function": "artifactAvailabilityProofId", + "idField": "proofId", + "input": { + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "providerId": "0x0dc433e7afcaecae8532a1bd432c3954072ee62a73d9112e57bfd01a001c393f", + "locationCommitment": "0x42dca9f7b94d6d927d5af2d65be01e2180f0f7992df017410fbe70118299eccd", + "storageReceiptCommitment": "0x1e71bf37d72b2b1a3dafd534a5fad68b62f8e00017ca170f211e963fbbc7d59a", + "availabilitySampleRoot": "0xd72d47a64f960ca8af6e1746c576f4211ed4238383684a438026b10f7c9f2c60", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "status": 7, + "nonce": "0xb68051d46145d6360b963e755c6950ea087bc7bbdb3ad4a0dc4508150a2c7685" + }, + "expected": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e", + "document": { + "schema": "flowchain.artifact_availability_proof.v0", + "proofId": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e", + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "providerId": "0x0dc433e7afcaecae8532a1bd432c3954072ee62a73d9112e57bfd01a001c393f", + "locationCommitment": "0x42dca9f7b94d6d927d5af2d65be01e2180f0f7992df017410fbe70118299eccd", + "storageReceiptCommitment": "0x1e71bf37d72b2b1a3dafd534a5fad68b62f8e00017ca170f211e963fbbc7d59a", + "availabilitySampleRoot": "0xd72d47a64f960ca8af6e1746c576f4211ed4238383684a438026b10f7c9f2c60", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "status": "available", + "statusCode": 7, + "nonce": "0xb68051d46145d6360b963e755c6950ea087bc7bbdb3ad4a0dc4508150a2c7685" + } + }, + { + "name": "verifier-module.demo", + "schemaPath": "../../schemas/flowmemory/verifier-module.schema.json", + "function": "verifierModuleId", + "idField": "moduleId", + "input": { + "ownerId": "0x5453d44b67a39bcbd94ad71b4499798ea0f5b3e27b22ce51e9343c0223a3d58a", + "codeRoot": "0x6900549a6f3c5becb720e7bc0176a85305dbfb1881a52ff84c269bddff77067c", + "manifestRoot": "0x4d491666ff5482701f6ac44230cc7929030ce7f6f6b7b021c59b211eb88e6c1e", + "supportedModesRoot": "0xd9bbac634f1a0edb893028ea020757da28e1aae731be0702d708098c6d53a009", + "supportedChallengeTypesRoot": "0x4b8175b52291488cab4145ed9b34f0dcb4f6439d212e892909a0a0c9f3da1113", + "verifierSetRoot": "0xc4f5360009577f8e8cb3000867f5da8cb88b899cae39ef97737e98efc18bdbf3", + "moduleVersion": 0, + "status": 2 + }, + "expected": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360", + "document": { + "schema": "flowchain.verifier_module.v0", + "moduleId": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360", + "ownerId": "0x5453d44b67a39bcbd94ad71b4499798ea0f5b3e27b22ce51e9343c0223a3d58a", + "codeRoot": "0x6900549a6f3c5becb720e7bc0176a85305dbfb1881a52ff84c269bddff77067c", + "manifestRoot": "0x4d491666ff5482701f6ac44230cc7929030ce7f6f6b7b021c59b211eb88e6c1e", + "supportedModesRoot": "0xd9bbac634f1a0edb893028ea020757da28e1aae731be0702d708098c6d53a009", + "supportedChallengeTypesRoot": "0x4b8175b52291488cab4145ed9b34f0dcb4f6439d212e892909a0a0c9f3da1113", + "verifierSetRoot": "0xc4f5360009577f8e8cb3000867f5da8cb88b899cae39ef97737e98efc18bdbf3", + "moduleVersion": 0, + "status": "active", + "statusCode": 2 + } + }, + { + "name": "verifier-report.demo", + "schemaPath": "../../schemas/flowmemory/verifier-report.schema.json", + "function": "verifierReportHash", + "idField": "reportId", + "input": { + "reportSchemaHash": "0x487a3a70cf72c079fa8645f8d732cbe286f7f3aa0abd654f212ac1c1911a20ae", + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "verifierId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "verifierSetRoot": "0x96130fe314e14b7f7d4347094f6b5ec4338b1f7730bf505e59fd3e731753ff8b", + "status": 2, + "checksRoot": "0x48468783cf12adfeba9be8e0a5e250ab04b19d5034f7e1996610cf05f4fcef83", + "finalizedBlockNumber": "12345742", + "finalizedBlockHash": "0x1111111111111111111111111111111111111111111111111111111111111111", + "reportVersion": 0 + }, + "expected": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355", + "document": { + "schema": "flowchain.verifier_report.v0", + "reportId": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355", + "reportSchemaHash": "0x487a3a70cf72c079fa8645f8d732cbe286f7f3aa0abd654f212ac1c1911a20ae", + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "verifierId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "verifierSetRoot": "0x96130fe314e14b7f7d4347094f6b5ec4338b1f7730bf505e59fd3e731753ff8b", + "status": "verified", + "statusCode": 2, + "checksRoot": "0x48468783cf12adfeba9be8e0a5e250ab04b19d5034f7e1996610cf05f4fcef83", + "finalizedBlockNumber": "12345742", + "finalizedBlockHash": "0x1111111111111111111111111111111111111111111111111111111111111111", + "reportVersion": 0 + } + }, + { + "name": "memory-cell.demo", + "schemaPath": "../../schemas/flowmemory/memory-cell.schema.json", + "function": "memoryCellId", + "idField": "memoryCellId", + "input": { + "ownerAgentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "currentMemoryRoot": "0x4cddf39c05428ff95e92ad96a6a4199348dd19e9935b681ec3f111217f87dbc8", + "previousMemoryRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "lastDeltaRoot": "0xf8951ccd1d2827cfe0078df813223eb8b97c68adce39a9e07c6a92cb692ad010", + "sourceReceiptsRoot": "0xe20859136519b00db74fd38d9f4228de33eecfb3e554aaa9438ea2edc0d17e0c", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "updatedAtUnixMs": "1778702400000", + "cellVersion": 0 + }, + "expected": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "document": { + "schema": "flowchain.memory_cell.v0", + "memoryCellId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "ownerAgentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "currentMemoryRoot": "0x4cddf39c05428ff95e92ad96a6a4199348dd19e9935b681ec3f111217f87dbc8", + "previousMemoryRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "lastDeltaRoot": "0xf8951ccd1d2827cfe0078df813223eb8b97c68adce39a9e07c6a92cb692ad010", + "sourceReceiptsRoot": "0xe20859136519b00db74fd38d9f4228de33eecfb3e554aaa9438ea2edc0d17e0c", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "status": "active", + "updatedAtUnixMs": "1778702400000", + "cellVersion": 0 + } + }, + { + "name": "challenge.demo", + "schemaPath": "../../schemas/flowmemory/challenge.schema.json", + "function": "challengeId", + "idField": "challengeId", + "input": { + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "challengerId": "0x40dc731df288781313d04725dc79f969488b910d9ed2220695c0e249477ffc57", + "challengeType": 7, + "evidenceRoot": "0x0b6a5765989e49f9763082146b15d5b7e3ef614c3d12c9cfbbdcd940164b4c56", + "openedAtUnixMs": "1778702400000", + "deadlineUnixMs": "1779307200000", + "status": 1, + "nonce": "0x3fae75c35d96efdccce46b8d8223846defbb52752d3332afc0a799b84a55020d" + }, + "expected": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403", + "document": { + "schema": "flowchain.challenge.v0", + "challengeId": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403", + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "challengerId": "0x40dc731df288781313d04725dc79f969488b910d9ed2220695c0e249477ffc57", + "challengeType": "dependency_omission", + "challengeTypeCode": 7, + "evidenceRoot": "0x0b6a5765989e49f9763082146b15d5b7e3ef614c3d12c9cfbbdcd940164b4c56", + "openedAtUnixMs": "1778702400000", + "deadlineUnixMs": "1779307200000", + "status": "open", + "statusCode": 1, + "nonce": "0x3fae75c35d96efdccce46b8d8223846defbb52752d3332afc0a799b84a55020d" + } + }, + { + "name": "finality-receipt.demo", + "schemaPath": "../../schemas/flowmemory/finality-receipt.schema.json", + "function": "finalityReceiptId", + "idField": "finalityReceiptId", + "input": { + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "challengeRoot": "0xf8962b5f9cf19578b6fe3cebc986cd054d594c0674e1fa48387c0278c6522967", + "finalityState": 2, + "finalizedAtUnixMs": "0", + "finalizedBlockNumber": "0", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "policyHash": "0xa6c5cdc9afc15dea4b2de2ab4bf4fa1ec5a6acee82e1864319ad8c46d2ae826d" + }, + "expected": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf", + "document": { + "schema": "flowchain.finality_receipt.v0", + "finalityReceiptId": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf", + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "challengeRoot": "0xf8962b5f9cf19578b6fe3cebc986cd054d594c0674e1fa48387c0278c6522967", + "finalityState": "challengeable", + "finalityStateCode": 2, + "finalizedAtUnixMs": "0", + "finalizedBlockNumber": "0", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "policyHash": "0xa6c5cdc9afc15dea4b2de2ab4bf4fa1ec5a6acee82e1864319ad8c46d2ae826d" + } + }, + { + "name": "hardware-signal-envelope.demo", + "schemaPath": "../../schemas/flowmemory/hardware-signal-envelope.schema.json", + "function": "hardwareSignalEnvelopeId", + "idField": "hardwareSignalEnvelopeId", + "input": { + "deviceId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signalRoot": "0xf57eaf258fac37071f818115db61e6bb48bbdfb41424316199ed0963d59a75b3", + "previousSignalEnvelopeId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "channelRoot": "0x280db3544e0aec306695543b1f7a1452e29b708d6df8749c293aec13f382944d", + "sequence": "1", + "observedAtUnixMs": "1778702400000", + "transport": 1, + "nonce": "0x1b85840b67182a89cf64394167db32108e00798b043aad5c6c2cab58d8726110" + }, + "expected": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10", + "document": { + "schema": "flowchain.hardware_signal_envelope.v0", + "hardwareSignalEnvelopeId": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10", + "deviceId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signalRoot": "0xf57eaf258fac37071f818115db61e6bb48bbdfb41424316199ed0963d59a75b3", + "previousSignalEnvelopeId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "channelRoot": "0x280db3544e0aec306695543b1f7a1452e29b708d6df8749c293aec13f382944d", + "sequence": "1", + "observedAtUnixMs": "1778702400000", + "transport": "local_simulator", + "transportCode": 1, + "status": "accepted", + "nonce": "0x1b85840b67182a89cf64394167db32108e00798b043aad5c6c2cab58d8726110" + } + }, + { + "name": "control-plane-provenance-response.demo", + "schemaPath": "../../schemas/flowmemory/control-plane-provenance-response.schema.json", + "function": "controlPlaneProvenanceResponseId", + "idField": "provenanceResponseId", + "input": { + "requestId": "0x147deb7c7f91259726ff0b4146c5249836a162f93c14562847cc15dac768e8d7", + "subjectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "memoryCellId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "responseBodyHash": "0x709a37c10de55cbcfe702a41d49e08ecdb95bfa3b7149b1d855b60ac5359f24b", + "issuedAtUnixMs": "1778702400000", + "responseVersion": 0 + }, + "expected": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb", + "document": { + "schema": "flowchain.control_plane_provenance_response.v0", + "provenanceResponseId": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb", + "requestId": "0x147deb7c7f91259726ff0b4146c5249836a162f93c14562847cc15dac768e8d7", + "subjectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "memoryCellId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "responseBodyHash": "0x709a37c10de55cbcfe702a41d49e08ecdb95bfa3b7149b1d855b60ac5359f24b", + "responseBody": { + "subject": "local-alpha-memory-cell", + "status": "challengeable", + "limitations": [ + "V0 binds IDs and commitments only.", + "V0 does not prove model output correctness." + ] + }, + "issuedAtUnixMs": "1778702400000", + "responseVersion": 0 + } + } + ], + "negative": [ + { + "name": "agent-account.swapped-policy-and-tool-roots", + "reason": "swapped-field-rejection", + "function": "agentAccountId", + "input": { + "namespaceId": "0x4c2eae268c3f97a510b66597873c6c08ae9e427a7c03cd383df6acfeda9bbf37", + "owner": "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1", + "policyRoot": "0x39079bde86c6743c81fd927a14012331688374b55118484529ce257317327120", + "toolPermissionsRoot": "0x20121b5daa2be4de0d9dbcae292d1d3466a4e0a8b6cc3149ce46c30c352a1f0e", + "modelAllowlistRoot": "0x00a463537f12e3419d4bf3655d28d93f3e189b9a89a3ad40c4819bbc4eb2acc9", + "memoryNamespaceRoot": "0x574eee506454973fb82863a3225ea78696b96907a17c360ad2c2b5234dfa2d83", + "spendingLimitPerEpoch": "0", + "nonce": "0x37e916697be966b19c0cd7aa6073e78ffb7ee5cf27a4392383f9cfe5fa5025bb" + }, + "mustNotEqual": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61" + }, + { + "name": "finality-receipt.swapped-receipt-and-report", + "reason": "swapped-field-rejection", + "function": "finalityReceiptId", + "input": { + "receiptId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "reportId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "challengeRoot": "0xf8962b5f9cf19578b6fe3cebc986cd054d594c0674e1fa48387c0278c6522967", + "finalityState": 2, + "finalizedAtUnixMs": "0", + "finalizedBlockNumber": "0", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "policyHash": "0xa6c5cdc9afc15dea4b2de2ab4bf4fa1ec5a6acee82e1864319ad8c46d2ae826d" + }, + "mustNotEqual": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf" + }, + { + "name": "memory-cell.malformed-current-root", + "reason": "malformed-hex-rejection", + "function": "memoryCellId", + "input": { + "ownerAgentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "currentMemoryRoot": "0xnot-a-bytes32", + "previousMemoryRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "lastDeltaRoot": "0xf8951ccd1d2827cfe0078df813223eb8b97c68adce39a9e07c6a92cb692ad010", + "sourceReceiptsRoot": "0xe20859136519b00db74fd38d9f4228de33eecfb3e554aaa9438ea2edc0d17e0c", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "updatedAtUnixMs": "1778702400000", + "cellVersion": 0 + }, + "throws": "invalid hex" + }, + { + "name": "agent-account.duplicate-id-list", + "reason": "duplicate-id-rejection", + "documents": [ + { + "schema": "flowchain.agent_account.v0", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61" + }, + { + "schema": "flowchain.agent_account.v0", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61" + } + ], + "duplicateId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61" + } + ], + "envelopes": { + "positive": [ + { + "name": "agent-account.demo.operator-signature-envelope", + "objectName": "agent-account.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "envelopeId": "0x55656083efaf8a511fbae76b2a1bb740b08c92959e506a14f489f0fedcef3279", + "signingDigest": "0x5a6640f50a22ae2d72ebe1d0687bd557d2d33d5de0fc6563ccafba17de48273e" + }, + "input": { + "objectId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "objectTypeHash": "0x0b32d0c8ec630542359a97b7b5c44804b7021b96433ba120572ad0609d81d029", + "domainSeparator": "0xff84e3bb0214d3812d1bf8521ab9d5b836c7746794e226af2a56a2efd0b65ee6", + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "signerRole": 1, + "sequence": "1", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xe9b99686c583dbed5b3bf743c2a3db8a5da8c8ceea4398eb45d57c518c555034" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x55656083efaf8a511fbae76b2a1bb740b08c92959e506a14f489f0fedcef3279", + "objectType": "agent_account", + "objectSchema": "flowchain.agent_account.v0", + "objectId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "objectTypeHash": "0x0b32d0c8ec630542359a97b7b5c44804b7021b96433ba120572ad0609d81d029", + "domain": "flowchain.local-alpha.v0.agent-account.id", + "domainSeparator": "0xff84e3bb0214d3812d1bf8521ab9d5b836c7746794e226af2a56a2efd0b65ee6", + "signerRole": "operator", + "signerRoleCode": 1, + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "sequence": "1", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xe9b99686c583dbed5b3bf743c2a3db8a5da8c8ceea4398eb45d57c518c555034", + "signingDigest": "0x5a6640f50a22ae2d72ebe1d0687bd557d2d33d5de0fc6563ccafba17de48273e", + "signature": "0xa9024e98d7ffacdfeb80e568609dc0ef5fac9c2b120762ab171e4e7e08f70bde0393d0eab85707c5c81aaf3318f5d9912e7e33af9db30e8842402984bb4dbb11" + } + }, + { + "name": "model-passport.demo.operator-signature-envelope", + "objectName": "model-passport.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879", + "envelopeId": "0x7f7eb2933ed962047f566b05a89a6572b398cf0de099c592827de5adf98ad830", + "signingDigest": "0xaf3b21f90c311952b732fbbfe58fd0cf9f5c5de4e130f6cdd0f59b59ef82c7bc" + }, + "input": { + "objectId": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879", + "objectTypeHash": "0x068eb5f8adc1d9e0b9c7bba728c6dc5b0fd01d25f895b4cf838c493981cfd8b7", + "domainSeparator": "0x9abbbfb63ea4784cfcd331c1cd76e009dbd88b7c4a05b08782778dc1bd2a804f", + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "signerRole": 1, + "sequence": "2", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xf73b964ab858057624a48b7dde73db2653ad9650d5a73644971471e9b0034d9a" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x7f7eb2933ed962047f566b05a89a6572b398cf0de099c592827de5adf98ad830", + "objectType": "model_passport", + "objectSchema": "flowchain.model_passport.v0", + "objectId": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879", + "objectTypeHash": "0x068eb5f8adc1d9e0b9c7bba728c6dc5b0fd01d25f895b4cf838c493981cfd8b7", + "domain": "flowchain.local-alpha.v0.model-passport.id", + "domainSeparator": "0x9abbbfb63ea4784cfcd331c1cd76e009dbd88b7c4a05b08782778dc1bd2a804f", + "signerRole": "operator", + "signerRoleCode": 1, + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "sequence": "2", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xf73b964ab858057624a48b7dde73db2653ad9650d5a73644971471e9b0034d9a", + "signingDigest": "0xaf3b21f90c311952b732fbbfe58fd0cf9f5c5de4e130f6cdd0f59b59ef82c7bc", + "signature": "0xeace6a95d927fb422334500535147fe4ba35f4ca1d97e8789e3ce3245d3cd5b742bde6b1edad69c845951fda688857545bf3d31f3a01749f7e078cc73285111d" + } + }, + { + "name": "work-receipt.demo.agent-signature-envelope", + "objectName": "work-receipt.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9", + "envelopeId": "0xa950d733414e06b7aff0823abd958a7974d65d4b5fe05674fab5a9fcf803af8e", + "signingDigest": "0xbd93059c8c963d193bc337ed6a480b285738a80583829cf74c323da81e82d64a" + }, + "input": { + "objectId": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9", + "objectTypeHash": "0x06e024249a151c7131610c5d00ee551983f967c010382a89004da89a6f158489", + "domainSeparator": "0x4638694e800bc411c242b45deb8d2a911fabbd6ae454c39bfc668a1b88ea315f", + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "signerRole": 2, + "sequence": "3", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x6a7818dd52eaf447f0807f0c2b65672139275fefb3ed0435840d48410f2abc64" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0xa950d733414e06b7aff0823abd958a7974d65d4b5fe05674fab5a9fcf803af8e", + "objectType": "work_receipt", + "objectSchema": "flowchain.work_receipt.v0", + "objectId": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9", + "objectTypeHash": "0x06e024249a151c7131610c5d00ee551983f967c010382a89004da89a6f158489", + "domain": "flowmemory.v0.work.receipt-id", + "domainSeparator": "0x4638694e800bc411c242b45deb8d2a911fabbd6ae454c39bfc668a1b88ea315f", + "signerRole": "agent", + "signerRoleCode": 2, + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "sequence": "3", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x6a7818dd52eaf447f0807f0c2b65672139275fefb3ed0435840d48410f2abc64", + "signingDigest": "0xbd93059c8c963d193bc337ed6a480b285738a80583829cf74c323da81e82d64a", + "signature": "0x8853f2fdee647dba9461ea8b9b45ab9d5cb943e5508f1861521010d9146955f669da89c56b93407e4be4c52d6c5032f34dd4a9bd00fc079768d817155705b136" + } + }, + { + "name": "artifact-availability-proof.demo.operator-signature-envelope", + "objectName": "artifact-availability-proof.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e", + "envelopeId": "0xeaa553befba878862c614b8ca9df9c3e5e90e6299ca415043e50d8cb2874f4b0", + "signingDigest": "0x6a0e253e6002840c3a8edbaf603211d156c1b5c56b8ddd5b0efa3753e5635da3" + }, + "input": { + "objectId": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e", + "objectTypeHash": "0x505f965c4ae6db350bdf73d2f85117ae099b4faec87b7ff83940e3854c6920c5", + "domainSeparator": "0xa7bbdb457725f7ad03fe4e6d2becb74c1ea54be06083f3d3e693f843615c7a20", + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "signerRole": 1, + "sequence": "4", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x64e8a1902689ca7d2c9eeb3200ddca8679faa549e898c639632a46cca55d88f2" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0xeaa553befba878862c614b8ca9df9c3e5e90e6299ca415043e50d8cb2874f4b0", + "objectType": "artifact_availability_proof", + "objectSchema": "flowchain.artifact_availability_proof.v0", + "objectId": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e", + "objectTypeHash": "0x505f965c4ae6db350bdf73d2f85117ae099b4faec87b7ff83940e3854c6920c5", + "domain": "flowchain.local-alpha.v0.artifact-availability-proof.id", + "domainSeparator": "0xa7bbdb457725f7ad03fe4e6d2becb74c1ea54be06083f3d3e693f843615c7a20", + "signerRole": "operator", + "signerRoleCode": 1, + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "sequence": "4", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x64e8a1902689ca7d2c9eeb3200ddca8679faa549e898c639632a46cca55d88f2", + "signingDigest": "0x6a0e253e6002840c3a8edbaf603211d156c1b5c56b8ddd5b0efa3753e5635da3", + "signature": "0xabeedc2cd0390ab361c7b544d1a5cd52445e098d36e59766ddde9e64bfd105c1358fe95b576f26ac9498187e52936becdc8fd4181bf2f16ee5290469f41034f9" + } + }, + { + "name": "verifier-module.demo.verifier-signature-envelope", + "objectName": "verifier-module.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360", + "envelopeId": "0x0db093584755eb839086ef8d06adb7f1f4283365abdc8e5fc0de3452a519b408", + "signingDigest": "0x0127126d3ca637a481b753b2e404a510d3a0ca97349ba907cfa3161f563cb836" + }, + "input": { + "objectId": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360", + "objectTypeHash": "0x9d02e1e5ef3686eef661fe474251de5ccffc5974c58c61fe6f34758c8a720275", + "domainSeparator": "0xfdb5ce2359d87d7546c9e5cdf604a270ffc2485dccc345df0c881daadd0e3aed", + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "signerRole": 3, + "sequence": "5", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xc2c56aa26345dc56be8c781635cb27c917d32b5da76cfc04996cd0d7cea1b49e" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x0db093584755eb839086ef8d06adb7f1f4283365abdc8e5fc0de3452a519b408", + "objectType": "verifier_module", + "objectSchema": "flowchain.verifier_module.v0", + "objectId": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360", + "objectTypeHash": "0x9d02e1e5ef3686eef661fe474251de5ccffc5974c58c61fe6f34758c8a720275", + "domain": "flowchain.local-alpha.v0.verifier-module.id", + "domainSeparator": "0xfdb5ce2359d87d7546c9e5cdf604a270ffc2485dccc345df0c881daadd0e3aed", + "signerRole": "verifier", + "signerRoleCode": 3, + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "publicKey": "0x02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "sequence": "5", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xc2c56aa26345dc56be8c781635cb27c917d32b5da76cfc04996cd0d7cea1b49e", + "signingDigest": "0x0127126d3ca637a481b753b2e404a510d3a0ca97349ba907cfa3161f563cb836", + "signature": "0x8d47ba1876c942f4eac15cfdc153406a47eb7233c9a44506702311755dd01d212933de6d1b96f7f5be49986325c5e4ea0f89ef4f27a8174520a466fa4c5d45fa" + } + }, + { + "name": "verifier-report.demo.verifier-signature-envelope", + "objectName": "verifier-report.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355", + "envelopeId": "0xbe0d02653b37c8c6fc9dd2691bad7d7ccfe7ad89dfca899a44760144aa30c295", + "signingDigest": "0xd93b37d75d937c09e9603c8159e20e396931d1fd1cb257a176864526cd7432b3" + }, + "input": { + "objectId": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355", + "objectTypeHash": "0x3c1d703293c54d61da59603a7ccdb51b8b5ca21a96ef34c34570864e1943c242", + "domainSeparator": "0x8ef53353c77dafe36cddcee05e4f11cc5027f7b54a9c0cbbc215a71bea8323f8", + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "signerRole": 3, + "sequence": "6", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x61e313795f9590163b38135b400bb0438d81787ec59ef9d628497320179a87d0" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0xbe0d02653b37c8c6fc9dd2691bad7d7ccfe7ad89dfca899a44760144aa30c295", + "objectType": "verifier_report", + "objectSchema": "flowchain.verifier_report.v0", + "objectId": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355", + "objectTypeHash": "0x3c1d703293c54d61da59603a7ccdb51b8b5ca21a96ef34c34570864e1943c242", + "domain": "flowmemory.v0.verifier.report-digest", + "domainSeparator": "0x8ef53353c77dafe36cddcee05e4f11cc5027f7b54a9c0cbbc215a71bea8323f8", + "signerRole": "verifier", + "signerRoleCode": 3, + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "publicKey": "0x02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "sequence": "6", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x61e313795f9590163b38135b400bb0438d81787ec59ef9d628497320179a87d0", + "signingDigest": "0xd93b37d75d937c09e9603c8159e20e396931d1fd1cb257a176864526cd7432b3", + "signature": "0x9870e8ce192cfaa2a78ab7a749076c5308218edb6918b75d9e04fe3403e29b6965ae945140b8d415af91d7bb1638e28cf06ac2b50889a33c0a9a137261c717ae" + } + }, + { + "name": "memory-cell.demo.agent-signature-envelope", + "objectName": "memory-cell.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "envelopeId": "0x374082e4aaa3c940eeba7b53d0348cf81415652a3e0127cccb403677b47674fd", + "signingDigest": "0x2df8a5742b883c13c7bb5ebec91c92a6283101236971f0d62128eaffb1e589cf" + }, + "input": { + "objectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "objectTypeHash": "0x6ed0f1045cef52eba52442242fbfc74a44bc1e0568866319b88e6c5b38ff43e0", + "domainSeparator": "0x06e4e0e2491dee22170b7dc2a29131b92db1bf405e1e4a9018b1f8b042c1f003", + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "signerRole": 2, + "sequence": "7", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xf4dfd21727eda874622b35788a9a8c4953fe53bcd9d12a97cf207bcbe88937f9" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x374082e4aaa3c940eeba7b53d0348cf81415652a3e0127cccb403677b47674fd", + "objectType": "memory_cell", + "objectSchema": "flowchain.memory_cell.v0", + "objectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "objectTypeHash": "0x6ed0f1045cef52eba52442242fbfc74a44bc1e0568866319b88e6c5b38ff43e0", + "domain": "flowchain.local-alpha.v0.memory-cell.id", + "domainSeparator": "0x06e4e0e2491dee22170b7dc2a29131b92db1bf405e1e4a9018b1f8b042c1f003", + "signerRole": "agent", + "signerRoleCode": 2, + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "sequence": "7", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xf4dfd21727eda874622b35788a9a8c4953fe53bcd9d12a97cf207bcbe88937f9", + "signingDigest": "0x2df8a5742b883c13c7bb5ebec91c92a6283101236971f0d62128eaffb1e589cf", + "signature": "0x07cd84afb338d899d25cdc420f46911789ea5da876a4e1f845a54ac35f90d8cd1ceb8769c02f6b2d28308658e645d691a46217c7d92fa8b0ae877e2bf9d878af" + } + }, + { + "name": "challenge.demo.agent-signature-envelope", + "objectName": "challenge.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403", + "envelopeId": "0x0b0269ba2354d34b121062b3aeb0918826695af5b56bc9796ebfe915bc19a57e", + "signingDigest": "0xa4b0a44c3d2292fec4d22d664d9babef4e8e925951160797221933b47ab05367" + }, + "input": { + "objectId": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403", + "objectTypeHash": "0x83372cb17c18bc1eefba613367a330e190119898aac881c685b08b6e47fb42d3", + "domainSeparator": "0x9ef9b9d51f8deab79f1b2a18cf1fd9cef8325daccd42015312cdc857c39c7568", + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "signerRole": 2, + "sequence": "8", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xe413acc238046a9cdf67715e02b2aeb359b242250554d29f764ef14634bafe0c" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x0b0269ba2354d34b121062b3aeb0918826695af5b56bc9796ebfe915bc19a57e", + "objectType": "challenge", + "objectSchema": "flowchain.challenge.v0", + "objectId": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403", + "objectTypeHash": "0x83372cb17c18bc1eefba613367a330e190119898aac881c685b08b6e47fb42d3", + "domain": "flowchain.local-alpha.v0.challenge.id", + "domainSeparator": "0x9ef9b9d51f8deab79f1b2a18cf1fd9cef8325daccd42015312cdc857c39c7568", + "signerRole": "agent", + "signerRoleCode": 2, + "signerId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "signerKeyId": "0x0cd3ace447934998e0819d90cf89904776a2407e816541c1c43b99d38c351893", + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", + "sequence": "8", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xe413acc238046a9cdf67715e02b2aeb359b242250554d29f764ef14634bafe0c", + "signingDigest": "0xa4b0a44c3d2292fec4d22d664d9babef4e8e925951160797221933b47ab05367", + "signature": "0x768a36b2053f7c8da468d7c422a057180c234cf766df24fff785c3a3370d9ed567adb7b5bd1bbf7098dfb3f2e7cb70fc1056d90e4037332ac3661ff959807319" + } + }, + { + "name": "finality-receipt.demo.verifier-signature-envelope", + "objectName": "finality-receipt.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf", + "envelopeId": "0x662920534f0ae5d94b327cc7374d91cced76cf7b79752f4c0ef44db2edcc0a8e", + "signingDigest": "0x4b2644f8ae78f7d15075e1d6037fd855b1b84e23d3d58c628e8e68dc464b6541" + }, + "input": { + "objectId": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf", + "objectTypeHash": "0x381c5cc90ae4f9e807ffbefd2190f856678a0a7d4ff518970bf95859c5c29560", + "domainSeparator": "0x20f563bef0df073d41d9b981bbc82d8a9606a6f1055fa0c541b8bca28efaaeb1", + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "signerRole": 3, + "sequence": "9", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x0acb03f13a6705e9458fac25c44575707ee7ab8f92104da4e3216230e11b72a8" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x662920534f0ae5d94b327cc7374d91cced76cf7b79752f4c0ef44db2edcc0a8e", + "objectType": "finality_receipt", + "objectSchema": "flowchain.finality_receipt.v0", + "objectId": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf", + "objectTypeHash": "0x381c5cc90ae4f9e807ffbefd2190f856678a0a7d4ff518970bf95859c5c29560", + "domain": "flowchain.local-alpha.v0.finality-receipt.id", + "domainSeparator": "0x20f563bef0df073d41d9b981bbc82d8a9606a6f1055fa0c541b8bca28efaaeb1", + "signerRole": "verifier", + "signerRoleCode": 3, + "signerId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "signerKeyId": "0x9bc6e07b6ca6b1f21697ed511d211b82186960d193036d5817f1a8a46a6daff5", + "publicKey": "0x02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9", + "sequence": "9", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x0acb03f13a6705e9458fac25c44575707ee7ab8f92104da4e3216230e11b72a8", + "signingDigest": "0x4b2644f8ae78f7d15075e1d6037fd855b1b84e23d3d58c628e8e68dc464b6541", + "signature": "0x31fbb8b88c5b56888a402c748333f56ccb51300852aab105cbb80d2a176aebf501a6eadf9bb452a41d31dd20fa043eff270601243e0e5a24fb6647bdd33d10b6" + } + }, + { + "name": "hardware-signal-envelope.demo.hardware-signature-envelope", + "objectName": "hardware-signal-envelope.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10", + "envelopeId": "0xf278b187bcb6bc7e0abf3b198555d0b018f54c4eced2580d2805dfc710034d07", + "signingDigest": "0x00c4b16aa80e0960887445ac34dda98f57d451d5d07d6564affcc35d89b46f14" + }, + "input": { + "objectId": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10", + "objectTypeHash": "0x9e89c0262e9aaa8bf0dbc60037de26f6368d42fce5dc49ee4301a663047be5ee", + "domainSeparator": "0x4344c72bae8d1c167094207afb2b3f64b8318b099ff3eaf5c8f5c518bf215863", + "signerId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signerKeyId": "0x2960db74c119e17ca2323f749c1df8bfdb1b7e5eaddf640d52fda9d96b59c61b", + "signerRole": 4, + "sequence": "10", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x35e2f19224f77e09e149fa37ef5db44d7e3f7175df36ba22c0df233457ebbcb5" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0xf278b187bcb6bc7e0abf3b198555d0b018f54c4eced2580d2805dfc710034d07", + "objectType": "hardware_signal_envelope", + "objectSchema": "flowchain.hardware_signal_envelope.v0", + "objectId": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10", + "objectTypeHash": "0x9e89c0262e9aaa8bf0dbc60037de26f6368d42fce5dc49ee4301a663047be5ee", + "domain": "flowchain.local-alpha.v0.hardware-signal-envelope.id", + "domainSeparator": "0x4344c72bae8d1c167094207afb2b3f64b8318b099ff3eaf5c8f5c518bf215863", + "signerRole": "hardware", + "signerRoleCode": 4, + "signerId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signerKeyId": "0x2960db74c119e17ca2323f749c1df8bfdb1b7e5eaddf640d52fda9d96b59c61b", + "publicKey": "0x02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13", + "sequence": "10", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0x35e2f19224f77e09e149fa37ef5db44d7e3f7175df36ba22c0df233457ebbcb5", + "signingDigest": "0x00c4b16aa80e0960887445ac34dda98f57d451d5d07d6564affcc35d89b46f14", + "signature": "0xd72b87d4d4547dff9366672f78fbe9bd6f494617dd14442b458612be200d8f2540b3684e6bc485ef763d18931393aebda3411fc550b83d7aba54a9af1384e0f5" + } + }, + { + "name": "control-plane-provenance-response.demo.operator-signature-envelope", + "objectName": "control-plane-provenance-response.demo", + "schemaPath": "../../schemas/flowmemory/local-signature-envelope.schema.json", + "function": "localSignatureEnvelopeHash", + "expected": { + "objectId": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb", + "envelopeId": "0x4580f51a5ca0eb672ce045a0e239707e977715919362612a258a01663bd2fc39", + "signingDigest": "0x7daa08228e60cb637c775723700f2245e414546158f4e230ac32c9a2a3e7d404" + }, + "input": { + "objectId": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb", + "objectTypeHash": "0x7a3514a376146e3a8988dd397b42da1579bf8d074a53a8e8f4d207415b84e8a7", + "domainSeparator": "0xfe47c0668c801d02e4e7c5af1c4131ba03a6547f329546ba23c9ba66b7e0e4e6", + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "signerRole": 1, + "sequence": "11", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xba6419eff070c057f965640d866f97e4a30b170e18f2c071b327b47b8ebedcde" + }, + "envelope": { + "schema": "flowchain.local_signature_envelope.v0", + "envelopeId": "0x4580f51a5ca0eb672ce045a0e239707e977715919362612a258a01663bd2fc39", + "objectType": "control_plane_provenance_response", + "objectSchema": "flowchain.control_plane_provenance_response.v0", + "objectId": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb", + "objectTypeHash": "0x7a3514a376146e3a8988dd397b42da1579bf8d074a53a8e8f4d207415b84e8a7", + "domain": "flowchain.local-alpha.v0.control-plane-provenance-response.id", + "domainSeparator": "0xfe47c0668c801d02e4e7c5af1c4131ba03a6547f329546ba23c9ba66b7e0e4e6", + "signerRole": "operator", + "signerRoleCode": 1, + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "sequence": "11", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xba6419eff070c057f965640d866f97e4a30b170e18f2c071b327b47b8ebedcde", + "signingDigest": "0x7daa08228e60cb637c775723700f2245e414546158f4e230ac32c9a2a3e7d404", + "signature": "0x1dd7f91706ecb742ab4cbde578dff7e1571eb892c3db90a358ba8b1db65c7e49153ccd063dce1ae932548fa3e9af40bacf1c0f42690895517343f7b7a3548ff4" + } + } + ], + "negative": [ + { + "name": "envelope.replay-agent-account-sequence", + "baseEnvelope": "agent-account.demo.operator-signature-envelope", + "mutation": { + "contextReplay": true + }, + "expectErrors": [ + "replay" + ] + }, + { + "name": "envelope.wrong-domain-model-passport", + "baseEnvelope": "model-passport.demo.operator-signature-envelope", + "mutation": { + "envelope": { + "domainFrom": "workReceiptId" + } + }, + "expectErrors": [ + "wrong-domain" + ] + }, + { + "name": "envelope.missing-signer-work-receipt", + "baseEnvelope": "work-receipt.demo.agent-signature-envelope", + "mutation": { + "deleteEnvelopeFields": [ + "signerId" + ] + }, + "expectErrors": [ + "missing-signer" + ] + }, + { + "name": "envelope.zero-hash-model-artifact-root", + "baseEnvelope": "model-passport.demo.operator-signature-envelope", + "mutation": { + "document": { + "artifactRoot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "expectErrors": [ + "zero-hash" + ] + }, + { + "name": "envelope.malformed-id-challenge", + "baseEnvelope": "challenge.demo.agent-signature-envelope", + "mutation": { + "document": { + "challengeId": "0x1234" + } + }, + "expectErrors": [ + "malformed-id" + ] + }, + { + "name": "envelope.malformed-dependency-memory-cell", + "baseEnvelope": "memory-cell.demo.agent-signature-envelope", + "mutation": { + "document": { + "dependencyRoot": "0x1234" + } + }, + "expectErrors": [ + "malformed-dependency" + ] + }, + { + "name": "envelope.bad-parent-root-memory-cell", + "baseEnvelope": "memory-cell.demo.agent-signature-envelope", + "mutation": { + "documentFromDocumentField": { + "previousMemoryRoot": "currentMemoryRoot" + } + }, + "expectErrors": [ + "bad-parent-root" + ] + }, + { + "name": "envelope.wrong-object-type-hardware", + "baseEnvelope": "hardware-signal-envelope.demo.hardware-signature-envelope", + "mutation": { + "envelope": { + "objectSchema": "flowchain.model_passport.v0", + "objectType": "model_passport" + } + }, + "expectErrors": [ + "wrong-object-type" + ] + }, + { + "name": "envelope.bad-signature-agent-account", + "baseEnvelope": "agent-account.demo.operator-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-model-passport", + "baseEnvelope": "model-passport.demo.operator-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-work-receipt", + "baseEnvelope": "work-receipt.demo.agent-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-artifact-availability-proof", + "baseEnvelope": "artifact-availability-proof.demo.operator-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-verifier-module", + "baseEnvelope": "verifier-module.demo.verifier-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-verifier-report", + "baseEnvelope": "verifier-report.demo.verifier-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-memory-cell", + "baseEnvelope": "memory-cell.demo.agent-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-challenge", + "baseEnvelope": "challenge.demo.agent-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-finality-receipt", + "baseEnvelope": "finality-receipt.demo.verifier-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-hardware-signal-envelope", + "baseEnvelope": "hardware-signal-envelope.demo.hardware-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } + }, + "expectErrors": [ + "bad-signature" + ] + }, + { + "name": "envelope.bad-signature-control-plane-provenance-response", + "baseEnvelope": "control-plane-provenance-response.demo.operator-signature-envelope", + "mutation": { + "envelope": { + "publicKey": "0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + } + }, + "expectErrors": [ + "bad-signature" + ] + } + ] + } +} diff --git a/crypto/fixtures/vectors.json b/crypto/fixtures/vectors.json index 961dc133..5283476c 100644 --- a/crypto/fixtures/vectors.json +++ b/crypto/fixtures/vectors.json @@ -1,6 +1,6 @@ { "schema": "flowmemory.crypto.test-vectors.v0", - "vectorCount": 21, + "vectorCount": 33, "vectors": [ { "name": "domain.flowPulseObservationId", @@ -271,6 +271,190 @@ "timestamp": 1778640000 }, "expected": "0x90cb545229eb785f0583ca5abafb3da199a5c68a1aa8ef140e169c024ca48e54" + }, + { + "name": "local-alpha.agentAccountId", + "function": "agentAccountId", + "input": { + "namespaceId": "0x4c2eae268c3f97a510b66597873c6c08ae9e427a7c03cd383df6acfeda9bbf37", + "owner": "0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1", + "policyRoot": "0x20121b5daa2be4de0d9dbcae292d1d3466a4e0a8b6cc3149ce46c30c352a1f0e", + "toolPermissionsRoot": "0x39079bde86c6743c81fd927a14012331688374b55118484529ce257317327120", + "modelAllowlistRoot": "0x00a463537f12e3419d4bf3655d28d93f3e189b9a89a3ad40c4819bbc4eb2acc9", + "memoryNamespaceRoot": "0x574eee506454973fb82863a3225ea78696b96907a17c360ad2c2b5234dfa2d83", + "spendingLimitPerEpoch": "0", + "nonce": "0x37e916697be966b19c0cd7aa6073e78ffb7ee5cf27a4392383f9cfe5fa5025bb" + }, + "expected": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61" + }, + { + "name": "local-alpha.modelPassportId", + "function": "modelPassportId", + "input": { + "providerHash": "0x1dcd953776be1cde4f3d9f516d8ecf3641d664d8c97623af60327315c5600d0a", + "modelFamilyHash": "0x91c830851e70677b8aa487b104e05230fdd5d2ae5ee26b5423ca223b154b58cc", + "versionHash": "0x7c56a7f2edbd518ffcf014b4155ec4ad47062390e3a1302550e5a080c5ef4975", + "licenseRoot": "0x7c4f5757bbcb3cb1c84df192e87f2ba40b9d4cacb1e62b612e604a8d831bc4ee", + "policyRoot": "0x519cc6db7ebafcfa1add95a09f9ef811013d86d3e76e1d4b5099f9a379a98bdb", + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "metadataHash": "0x198ae9ec53443e3a46f8762e4b9ee166c2927d7faec07ce2bdc8714859504d17", + "nonce": "0x6550e26ef27367750192911d54ae8c97af6f828e52f4b696a25f215581a34b6b" + }, + "expected": "0xf1e4695d11203b1fd1702d4294b001387da6f6e66278e6018026eab22fa38879" + }, + { + "name": "local-alpha.memoryCellId", + "function": "memoryCellId", + "input": { + "ownerAgentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "currentMemoryRoot": "0x4cddf39c05428ff95e92ad96a6a4199348dd19e9935b681ec3f111217f87dbc8", + "previousMemoryRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "lastDeltaRoot": "0xf8951ccd1d2827cfe0078df813223eb8b97c68adce39a9e07c6a92cb692ad010", + "sourceReceiptsRoot": "0xe20859136519b00db74fd38d9f4228de33eecfb3e554aaa9438ea2edc0d17e0c", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "updatedAtUnixMs": "1778702400000", + "cellVersion": 0 + }, + "expected": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f" + }, + { + "name": "local-alpha.artifactAvailabilityProofId", + "function": "artifactAvailabilityProofId", + "input": { + "artifactRoot": "0x14d1fb24e2da3cdb25d55912b5f7b56fde462707343f827791dfb1c3945a0a99", + "providerId": "0x0dc433e7afcaecae8532a1bd432c3954072ee62a73d9112e57bfd01a001c393f", + "locationCommitment": "0x42dca9f7b94d6d927d5af2d65be01e2180f0f7992df017410fbe70118299eccd", + "storageReceiptCommitment": "0x1e71bf37d72b2b1a3dafd534a5fad68b62f8e00017ca170f211e963fbbc7d59a", + "availabilitySampleRoot": "0xd72d47a64f960ca8af6e1746c576f4211ed4238383684a438026b10f7c9f2c60", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "status": 7, + "nonce": "0xb68051d46145d6360b963e755c6950ea087bc7bbdb3ad4a0dc4508150a2c7685" + }, + "expected": "0x9d5fae6b0098c96fc0ab37e75ca34cef4a9dfcf18c7153762ba75ddf563e536e" + }, + { + "name": "local-alpha.verifierModuleId", + "function": "verifierModuleId", + "input": { + "ownerId": "0x5453d44b67a39bcbd94ad71b4499798ea0f5b3e27b22ce51e9343c0223a3d58a", + "codeRoot": "0x6900549a6f3c5becb720e7bc0176a85305dbfb1881a52ff84c269bddff77067c", + "manifestRoot": "0x4d491666ff5482701f6ac44230cc7929030ce7f6f6b7b021c59b211eb88e6c1e", + "supportedModesRoot": "0xd9bbac634f1a0edb893028ea020757da28e1aae731be0702d708098c6d53a009", + "supportedChallengeTypesRoot": "0x4b8175b52291488cab4145ed9b34f0dcb4f6439d212e892909a0a0c9f3da1113", + "verifierSetRoot": "0xc4f5360009577f8e8cb3000867f5da8cb88b899cae39ef97737e98efc18bdbf3", + "moduleVersion": 0, + "status": 2 + }, + "expected": "0xbb9456a90fd97dfe26d07d3a39111a43484568d9b2088e82ca64d86487e5e360" + }, + { + "name": "local-alpha.challengeId", + "function": "challengeId", + "input": { + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "challengerId": "0x40dc731df288781313d04725dc79f969488b910d9ed2220695c0e249477ffc57", + "challengeType": 7, + "evidenceRoot": "0x0b6a5765989e49f9763082146b15d5b7e3ef614c3d12c9cfbbdcd940164b4c56", + "openedAtUnixMs": "1778702400000", + "deadlineUnixMs": "1779307200000", + "status": 1, + "nonce": "0x3fae75c35d96efdccce46b8d8223846defbb52752d3332afc0a799b84a55020d" + }, + "expected": "0x184dbda3f9e19adfe64d8ef4636dc9a3e6ab8f62761589653816dc574ffb3403" + }, + { + "name": "local-alpha.finalityReceiptId", + "function": "finalityReceiptId", + "input": { + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "challengeRoot": "0xf8962b5f9cf19578b6fe3cebc986cd054d594c0674e1fa48387c0278c6522967", + "finalityState": 2, + "finalizedAtUnixMs": "0", + "finalizedBlockNumber": "0", + "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "policyHash": "0xa6c5cdc9afc15dea4b2de2ab4bf4fa1ec5a6acee82e1864319ad8c46d2ae826d" + }, + "expected": "0x95216aeaec225965a4ce35eb2b136e27819642e68284201feade0d68dc4f9ddf" + }, + { + "name": "local-alpha.controlPlaneProvenanceResponseId", + "function": "controlPlaneProvenanceResponseId", + "input": { + "requestId": "0x147deb7c7f91259726ff0b4146c5249836a162f93c14562847cc15dac768e8d7", + "subjectId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "agentId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "receiptId": "0x8e89965b455212cb3767352ae3adb0bb5dd0d59fba141cb5064245d05bdbb2aa", + "reportId": "0x9577aa6df7026dfe6f46042d71397769591841ee8e0fd23bca3160a2032d2925", + "memoryCellId": "0x30823bd70635dac8e0b72968f57f46450566ac4dede63820f7ceafdfb7a4f13f", + "dependencyRoot": "0x87e2cc37cbb9eee123e6f0a84be9eb0bec68c0e4f7e35c1c119cf4a8015d56c6", + "responseBodyHash": "0x709a37c10de55cbcfe702a41d49e08ecdb95bfa3b7149b1d855b60ac5359f24b", + "issuedAtUnixMs": "1778702400000", + "responseVersion": 0 + }, + "expected": "0xb0336e11f4e939bbf8b423c7d57cc383a9cdf4982fb90b004c6d94ea5a3ec0eb" + }, + { + "name": "local-alpha.workReceiptId", + "function": "workReceiptId", + "input": { + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "workerId": "0x7803fe537f4b6e4ddd47f00b97a87c06aad1e42e22b83fdb522268e393319598", + "workerSequence": "1", + "nonce": "0x3574313751905cc45384e0a3f62258d38e9c64735e29bcee180459bb16cd4039" + }, + "expected": "0xb7404c2b88e7f6a1991dfc5294f8f78932cbbf00ebecf302a1139950672f81f9" + }, + { + "name": "local-alpha.verifierReportHash", + "function": "verifierReportHash", + "input": { + "reportSchemaHash": "0x487a3a70cf72c079fa8645f8d732cbe286f7f3aa0abd654f212ac1c1911a20ae", + "observationId": "0xd80d0a3b317ceae266c9b7983c5a9376529f457a01469c96d8d3fd5a6c2d8a3f", + "receiptHash": "0xca2ebca63e004ff4b0ca9766acbb2862b45059a480d911b67dbc25e937c2e733", + "verifierId": "0xaf0bdaa3ef421cfa8494019fb436baabcfdc65b55cf858c2d605a348c8c0aa48", + "verifierSetRoot": "0x96130fe314e14b7f7d4347094f6b5ec4338b1f7730bf505e59fd3e731753ff8b", + "status": 2, + "checksRoot": "0x48468783cf12adfeba9be8e0a5e250ab04b19d5034f7e1996610cf05f4fcef83", + "finalizedBlockNumber": "12345742", + "finalizedBlockHash": "0x1111111111111111111111111111111111111111111111111111111111111111", + "reportVersion": 0 + }, + "expected": "0x1b1c2940d6e83ee78a7e0a8285e4ce2530da1ce7964817806e61520a2e767355" + }, + { + "name": "local-alpha.hardwareSignalEnvelopeId", + "function": "hardwareSignalEnvelopeId", + "input": { + "deviceId": "0xc3a21c4e3c455b2388d06fb384165ff7156a3d40d877a19f88d814a8a1edeaea", + "signalRoot": "0xf57eaf258fac37071f818115db61e6bb48bbdfb41424316199ed0963d59a75b3", + "previousSignalEnvelopeId": "0x0000000000000000000000000000000000000000000000000000000000000000", + "channelRoot": "0x280db3544e0aec306695543b1f7a1452e29b708d6df8749c293aec13f382944d", + "sequence": "1", + "observedAtUnixMs": "1778702400000", + "transport": 1, + "nonce": "0x1b85840b67182a89cf64394167db32108e00798b043aad5c6c2cab58d8726110" + }, + "expected": "0xde6601ee3fc7e925d2d54b1dca26cf7cb560432f066f93b3f3bf1f31b4934a10" + }, + { + "name": "local-alpha.localSignatureEnvelopeHash.agent-account", + "function": "localSignatureEnvelopeHash", + "input": { + "objectId": "0xe4982e2682c9dd11caf102d2e0c9567ffad56850f1c69086b3996b77495fbb61", + "objectTypeHash": "0x0b32d0c8ec630542359a97b7b5c44804b7021b96433ba120572ad0609d81d029", + "domainSeparator": "0xff84e3bb0214d3812d1bf8521ab9d5b836c7746794e226af2a56a2efd0b65ee6", + "signerId": "0x06739c78255ec573518e97ffa9d2c5e11f49d49e0c65217c77d710a558a57f21", + "signerKeyId": "0x2409a6f84adce8b773bb8f47e18b4179df21e1957816c464efa481118f25d40a", + "signerRole": 1, + "sequence": "1", + "issuedAtUnixMs": "1778702400000", + "expiresAtUnixMs": "1810238400000", + "nonce": "0xe9b99686c583dbed5b3bf743c2a3db8a5da8c8ceea4398eb45d57c518c555034" + }, + "expected": "0x55656083efaf8a511fbae76b2a1bb740b08c92959e506a14f489f0fedcef3279" } ] } diff --git a/crypto/package-lock.json b/crypto/package-lock.json index 9d69e1a7..cd9a0a79 100644 --- a/crypto/package-lock.json +++ b/crypto/package-lock.json @@ -11,6 +11,10 @@ "@noble/hashes": "2.2.0", "@noble/secp256k1": "3.1.0" }, + "devDependencies": { + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1" + }, "engines": { "node": ">=20.19.0" } @@ -35,6 +39,82 @@ "funding": { "url": "https://paulmillr.com/funding/" } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } } } } diff --git a/crypto/package.json b/crypto/package.json index e1ac8fff..088ec3f9 100644 --- a/crypto/package.json +++ b/crypto/package.json @@ -15,7 +15,8 @@ "scripts": { "test": "node --test", "vectors": "node src/cli.js", - "validate:vectors": "node src/validate-vectors.js" + "validate:vectors": "node src/validate-vectors.js", + "validate:local-alpha": "node src/validate-local-alpha-fixtures.js" }, "dependencies": { "@noble/hashes": "2.2.0", @@ -23,5 +24,9 @@ }, "engines": { "node": ">=20.19.0" + }, + "devDependencies": { + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1" } } diff --git a/crypto/src/constants.js b/crypto/src/constants.js index 775d8f4d..d5231e30 100644 --- a/crypto/src/constants.js +++ b/crypto/src/constants.js @@ -41,6 +41,26 @@ export const TYPE_STRINGS = Object.freeze({ "FlowMemoryVerifierIdentityV0(bytes32 operatorId,bytes32 verifierKeyId,bytes32 verifierSetRoot)", devnetBlockHashV0: "FlowMemoryDevnetBlockV0(uint256 chainId,uint64 blockNumber,bytes32 parentHash,bytes32 stateRoot,uint64 timestamp)", + agentAccountV0: + "FlowChainAgentAccountV0(bytes32 namespaceId,address owner,bytes32 policyRoot,bytes32 toolPermissionsRoot,bytes32 modelAllowlistRoot,bytes32 memoryNamespaceRoot,uint256 spendingLimitPerEpoch,bytes32 nonce)", + modelPassportV0: + "FlowChainModelPassportV0(bytes32 providerHash,bytes32 modelFamilyHash,bytes32 versionHash,bytes32 licenseRoot,bytes32 policyRoot,bytes32 artifactRoot,bytes32 metadataHash,bytes32 nonce)", + memoryCellV0: + "FlowChainMemoryCellV0(bytes32 ownerAgentId,bytes32 currentMemoryRoot,bytes32 previousMemoryRoot,bytes32 lastDeltaRoot,bytes32 sourceReceiptsRoot,bytes32 dependencyRoot,uint64 updatedAtUnixMs,uint16 cellVersion)", + artifactAvailabilityProofV0: + "FlowChainArtifactAvailabilityProofV0(bytes32 artifactRoot,bytes32 providerId,bytes32 locationCommitment,bytes32 storageReceiptCommitment,bytes32 availabilitySampleRoot,uint64 issuedAtUnixMs,uint64 expiresAtUnixMs,uint8 status,bytes32 nonce)", + verifierModuleV0: + "FlowChainVerifierModuleV0(bytes32 ownerId,bytes32 codeRoot,bytes32 manifestRoot,bytes32 supportedModesRoot,bytes32 supportedChallengeTypesRoot,bytes32 verifierSetRoot,uint16 moduleVersion,uint8 status)", + challengeV0: + "FlowChainChallengeV0(bytes32 receiptId,bytes32 challengerId,uint8 challengeType,bytes32 evidenceRoot,uint64 openedAtUnixMs,uint64 deadlineUnixMs,uint8 status,bytes32 nonce)", + finalityReceiptV0: + "FlowChainFinalityReceiptV0(bytes32 receiptId,bytes32 reportId,bytes32 challengeRoot,uint8 finalityState,uint64 finalizedAtUnixMs,uint64 finalizedBlockNumber,bytes32 finalizedBlockHash,bytes32 policyHash)", + hardwareSignalEnvelopeV0: + "FlowChainHardwareSignalEnvelopeV0(bytes32 deviceId,bytes32 signalRoot,bytes32 previousSignalEnvelopeId,bytes32 channelRoot,uint64 sequence,uint64 observedAtUnixMs,uint8 transport,bytes32 nonce)", + controlPlaneProvenanceResponseV0: + "FlowChainControlPlaneProvenanceResponseV0(bytes32 requestId,bytes32 subjectId,bytes32 agentId,bytes32 receiptId,bytes32 reportId,bytes32 memoryCellId,bytes32 dependencyRoot,bytes32 responseBodyHash,uint64 issuedAtUnixMs,uint16 responseVersion)", + localSignatureEnvelopeV0: + "FlowChainLocalSignatureEnvelopeV0(bytes32 objectId,bytes32 objectTypeHash,bytes32 domainSeparator,bytes32 signerId,bytes32 signerKeyId,uint8 signerRole,uint64 sequence,uint64 issuedAtUnixMs,uint64 expiresAtUnixMs,bytes32 nonce)", eip712Domain: "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)" }); @@ -58,7 +78,17 @@ export const DOMAIN_STRINGS = Object.freeze({ verifierIdentity: "flowmemory.v0.verifier.identity", merkleLeaf: "flowmemory.v0.merkle.leaf", merkleInternalNode: "flowmemory.v0.merkle.internal-node", - devnetBlockHash: "flowmemory.v0.devnet.block-hash" + devnetBlockHash: "flowmemory.v0.devnet.block-hash", + agentAccountId: "flowchain.local-alpha.v0.agent-account.id", + modelPassportId: "flowchain.local-alpha.v0.model-passport.id", + memoryCellId: "flowchain.local-alpha.v0.memory-cell.id", + artifactAvailabilityProofId: "flowchain.local-alpha.v0.artifact-availability-proof.id", + verifierModuleId: "flowchain.local-alpha.v0.verifier-module.id", + challengeId: "flowchain.local-alpha.v0.challenge.id", + finalityReceiptId: "flowchain.local-alpha.v0.finality-receipt.id", + hardwareSignalEnvelopeId: "flowchain.local-alpha.v0.hardware-signal-envelope.id", + controlPlaneProvenanceResponseId: "flowchain.local-alpha.v0.control-plane-provenance-response.id", + localSignatureEnvelope: "flowchain.local-alpha.v0.local-signature-envelope" }); export const MERKLE_SCHEME_V0 = "FM-MERKLE-KECCAK256-BINARY-V0"; @@ -73,3 +103,58 @@ export const VERIFIER_STATUSES = Object.freeze({ reorged: 6, superseded: 7 }); + +export const LOCAL_ALPHA_OBJECT_STATUSES = Object.freeze({ + draft: 1, + active: 2, + paused: 3, + revoked: 4, + deprecated: 5, + rejected: 6, + available: 7, + unavailable: 8, + expired: 9 +}); + +export const LOCAL_ALPHA_CHALLENGE_TYPES = Object.freeze({ + missingArtifact: 1, + invalidArtifactRoot: 2, + missingModelPassport: 3, + memoryParentMismatch: 4, + policyViolation: 5, + deterministicReplayFailure: 6, + dependencyOmission: 7 +}); + +export const LOCAL_ALPHA_CHALLENGE_STATUSES = Object.freeze({ + open: 1, + submitterWins: 2, + challengerWins: 3, + unresolved: 4, + expired: 5 +}); + +export const LOCAL_ALPHA_FINALITY_STATES = Object.freeze({ + provisional: 1, + challengeable: 2, + challenged: 3, + accepted: 4, + rejected: 5, + finalized: 6, + superseded: 7, + reorged: 8 +}); + +export const LOCAL_ALPHA_HARDWARE_TRANSPORTS = Object.freeze({ + localSimulator: 1, + usbSerial: 2, + loraControl: 3, + meshtasticControl: 4 +}); + +export const LOCAL_ALPHA_SIGNER_ROLES = Object.freeze({ + operator: 1, + agent: 2, + verifier: 3, + hardware: 4 +}); diff --git a/crypto/src/index.d.ts b/crypto/src/index.d.ts index 6aa666e3..81b0058d 100644 --- a/crypto/src/index.d.ts +++ b/crypto/src/index.d.ts @@ -185,6 +185,139 @@ export interface DevnetBlockInput { timestamp: number | bigint | string; } +export interface AgentAccountInput { + namespaceId: Bytes32; + owner: Address; + policyRoot: Bytes32; + toolPermissionsRoot: Bytes32; + modelAllowlistRoot: Bytes32; + memoryNamespaceRoot: Bytes32; + spendingLimitPerEpoch: number | bigint | string; + nonce: Bytes32; +} + +export interface ModelPassportInput { + providerHash: Bytes32; + modelFamilyHash: Bytes32; + versionHash: Bytes32; + licenseRoot: Bytes32; + policyRoot: Bytes32; + artifactRoot: Bytes32; + metadataHash: Bytes32; + nonce: Bytes32; +} + +export interface MemoryCellInput { + ownerAgentId: Bytes32; + currentMemoryRoot: Bytes32; + previousMemoryRoot: Bytes32; + lastDeltaRoot: Bytes32; + sourceReceiptsRoot: Bytes32; + dependencyRoot: Bytes32; + updatedAtUnixMs: number | bigint | string; + cellVersion: number | bigint | string; +} + +export interface ArtifactAvailabilityProofInput { + artifactRoot: Bytes32; + providerId: Bytes32; + locationCommitment: Bytes32; + storageReceiptCommitment: Bytes32; + availabilitySampleRoot: Bytes32; + issuedAtUnixMs: number | bigint | string; + expiresAtUnixMs: number | bigint | string; + status: number | bigint | string; + nonce: Bytes32; +} + +export interface VerifierModuleInput { + ownerId: Bytes32; + codeRoot: Bytes32; + manifestRoot: Bytes32; + supportedModesRoot: Bytes32; + supportedChallengeTypesRoot: Bytes32; + verifierSetRoot: Bytes32; + moduleVersion: number | bigint | string; + status: number | bigint | string; +} + +export interface ChallengeInput { + receiptId: Bytes32; + challengerId: Bytes32; + challengeType: number | bigint | string; + evidenceRoot: Bytes32; + openedAtUnixMs: number | bigint | string; + deadlineUnixMs: number | bigint | string; + status: number | bigint | string; + nonce: Bytes32; +} + +export interface FinalityReceiptInput { + receiptId: Bytes32; + reportId: Bytes32; + challengeRoot: Bytes32; + finalityState: number | bigint | string; + finalizedAtUnixMs: number | bigint | string; + finalizedBlockNumber: number | bigint | string; + finalizedBlockHash: Bytes32; + policyHash: Bytes32; +} + +export interface ControlPlaneProvenanceResponseInput { + requestId: Bytes32; + subjectId: Bytes32; + agentId: Bytes32; + receiptId: Bytes32; + reportId: Bytes32; + memoryCellId: Bytes32; + dependencyRoot: Bytes32; + responseBodyHash: Bytes32; + issuedAtUnixMs: number | bigint | string; + responseVersion: number | bigint | string; +} + +export interface HardwareSignalEnvelopeInput { + deviceId: Bytes32; + signalRoot: Bytes32; + previousSignalEnvelopeId: Bytes32; + channelRoot: Bytes32; + sequence: number | bigint | string; + observedAtUnixMs: number | bigint | string; + transport: number | bigint | string; + nonce: Bytes32; +} + +export interface LocalSignatureEnvelopeInput { + objectId: Bytes32; + objectTypeHash: Bytes32; + domainSeparator: Bytes32; + signerId: Bytes32; + signerKeyId: Bytes32; + signerRole: number | bigint | string; + sequence: number | bigint | string; + issuedAtUnixMs: number | bigint | string; + expiresAtUnixMs: number | bigint | string; + nonce: Bytes32; +} + +export interface LocalSignatureEnvelopePayload { + structHash: Bytes32; + signingDigest: Bytes32; +} + +export interface LocalAlphaEnvelopeValidationInput { + document: Record; + envelope: Record; + context?: { + seenSequences?: Set; + }; +} + +export interface LocalAlphaEnvelopeValidationResult { + valid: boolean; + errors: string[]; +} + export const ZERO_BYTES32: Bytes32; export const FLOWPULSE_SCHEMA_ID_PREIMAGE: string; export const FLOWPULSE_EVENT_SIGNATURE: string; @@ -192,6 +325,12 @@ export const TYPE_STRINGS: Readonly>; export const DOMAIN_STRINGS: Readonly>; export const MERKLE_SCHEME_V0: string; export const VERIFIER_STATUSES: Readonly>; +export const LOCAL_ALPHA_OBJECT_STATUSES: Readonly>; +export const LOCAL_ALPHA_CHALLENGE_TYPES: Readonly>; +export const LOCAL_ALPHA_CHALLENGE_STATUSES: Readonly>; +export const LOCAL_ALPHA_FINALITY_STATES: Readonly>; +export const LOCAL_ALPHA_HARDWARE_TRANSPORTS: Readonly>; +export const LOCAL_ALPHA_SIGNER_ROLES: Readonly>; export function strip0x(value: string): string; export function bytesToHex(bytes: Uint8Array): Hex; @@ -269,3 +408,25 @@ export function workReceiptId(input: WorkReceiptInput): Bytes32; export function workerIdentity(input: WorkerIdentityInput): Bytes32; export function verifierIdentity(input: VerifierIdentityInput): Bytes32; export function devnetBlockHash(input: DevnetBlockInput): Bytes32; +export function agentAccountId(input: AgentAccountInput): Bytes32; +export function modelPassportId(input: ModelPassportInput): Bytes32; +export function memoryCellId(input: MemoryCellInput): Bytes32; +export function artifactAvailabilityProofId(input: ArtifactAvailabilityProofInput): Bytes32; +export function verifierModuleId(input: VerifierModuleInput): Bytes32; +export function challengeId(input: ChallengeInput): Bytes32; +export function finalityReceiptId(input: FinalityReceiptInput): Bytes32; +export function hardwareSignalEnvelopeId(input: HardwareSignalEnvelopeInput): Bytes32; +export function controlPlaneProvenanceResponseId(input: ControlPlaneProvenanceResponseInput): Bytes32; +export function localSignatureEnvelopeHash(input: LocalSignatureEnvelopeInput): Bytes32; +export const localSignatureEnvelopeId: typeof localSignatureEnvelopeHash; +export function localSignatureEnvelopePayload(input: LocalSignatureEnvelopeInput): LocalSignatureEnvelopePayload; +export function localAlphaObjectTypeHash(objectSchema: string): Bytes32; +export const LOCAL_ALPHA_OBJECT_DESCRIPTORS: Readonly>; +export function localAlphaObjectDescriptor(objectSchema: string): unknown; +export function localAlphaObjectInput(document: Record): unknown; +export function localAlphaObjectId(document: Record): Bytes32; +export function localAlphaEnvelopeReplayKey(envelope: Record): string; +export function localSignatureEnvelopeInput(envelope: Record): LocalSignatureEnvelopeInput; +export function validateLocalAlphaEnvelope( + input: LocalAlphaEnvelopeValidationInput +): LocalAlphaEnvelopeValidationResult; diff --git a/crypto/src/index.js b/crypto/src/index.js index ad50cab2..dd165ee2 100644 --- a/crypto/src/index.js +++ b/crypto/src/index.js @@ -5,3 +5,4 @@ export * from "./encoding.js"; export * from "./flowpulse.js"; export * from "./hashes.js"; export * from "./merkle.js"; +export * from "./objects.js"; diff --git a/crypto/src/objects.js b/crypto/src/objects.js new file mode 100644 index 00000000..5a466c10 --- /dev/null +++ b/crypto/src/objects.js @@ -0,0 +1,707 @@ +import { + DOMAIN_STRINGS, + LOCAL_ALPHA_FINALITY_STATES, + LOCAL_ALPHA_SIGNER_ROLES, + TYPE_STRINGS, + ZERO_BYTES32 +} from "./constants.js"; +import { hexToBytes } from "./encoding.js"; +import { verifyDigest } from "./attestations.js"; +import { eip712Digest, verifierReportHash } from "./flowpulse.js"; +import { domainSeparator, keccakUtf8, typedHash } from "./hashes.js"; +import { workReceiptId } from "./domains.js"; + +export function agentAccountId({ + namespaceId, + owner, + policyRoot, + toolPermissionsRoot, + modelAllowlistRoot, + memoryNamespaceRoot, + spendingLimitPerEpoch, + nonce +}) { + return typedHash(TYPE_STRINGS.agentAccountV0, [ + ["bytes32", namespaceId], + ["address", owner], + ["bytes32", policyRoot], + ["bytes32", toolPermissionsRoot], + ["bytes32", modelAllowlistRoot], + ["bytes32", memoryNamespaceRoot], + ["uint256", spendingLimitPerEpoch], + ["bytes32", nonce] + ]); +} + +export function modelPassportId({ + providerHash, + modelFamilyHash, + versionHash, + licenseRoot, + policyRoot, + artifactRoot, + metadataHash, + nonce +}) { + return typedHash(TYPE_STRINGS.modelPassportV0, [ + ["bytes32", providerHash], + ["bytes32", modelFamilyHash], + ["bytes32", versionHash], + ["bytes32", licenseRoot], + ["bytes32", policyRoot], + ["bytes32", artifactRoot], + ["bytes32", metadataHash], + ["bytes32", nonce] + ]); +} + +export function memoryCellId({ + ownerAgentId, + currentMemoryRoot, + previousMemoryRoot, + lastDeltaRoot, + sourceReceiptsRoot, + dependencyRoot, + updatedAtUnixMs, + cellVersion +}) { + return typedHash(TYPE_STRINGS.memoryCellV0, [ + ["bytes32", ownerAgentId], + ["bytes32", currentMemoryRoot], + ["bytes32", previousMemoryRoot], + ["bytes32", lastDeltaRoot], + ["bytes32", sourceReceiptsRoot], + ["bytes32", dependencyRoot], + ["uint64", updatedAtUnixMs], + ["uint16", cellVersion] + ]); +} + +export function artifactAvailabilityProofId({ + artifactRoot, + providerId, + locationCommitment, + storageReceiptCommitment, + availabilitySampleRoot, + issuedAtUnixMs, + expiresAtUnixMs, + status, + nonce +}) { + return typedHash(TYPE_STRINGS.artifactAvailabilityProofV0, [ + ["bytes32", artifactRoot], + ["bytes32", providerId], + ["bytes32", locationCommitment], + ["bytes32", storageReceiptCommitment], + ["bytes32", availabilitySampleRoot], + ["uint64", issuedAtUnixMs], + ["uint64", expiresAtUnixMs], + ["uint8", status], + ["bytes32", nonce] + ]); +} + +export function verifierModuleId({ + ownerId, + codeRoot, + manifestRoot, + supportedModesRoot, + supportedChallengeTypesRoot, + verifierSetRoot, + moduleVersion, + status +}) { + return typedHash(TYPE_STRINGS.verifierModuleV0, [ + ["bytes32", ownerId], + ["bytes32", codeRoot], + ["bytes32", manifestRoot], + ["bytes32", supportedModesRoot], + ["bytes32", supportedChallengeTypesRoot], + ["bytes32", verifierSetRoot], + ["uint16", moduleVersion], + ["uint8", status] + ]); +} + +export function challengeId({ + receiptId, + challengerId, + challengeType, + evidenceRoot, + openedAtUnixMs, + deadlineUnixMs, + status, + nonce +}) { + return typedHash(TYPE_STRINGS.challengeV0, [ + ["bytes32", receiptId], + ["bytes32", challengerId], + ["uint8", challengeType], + ["bytes32", evidenceRoot], + ["uint64", openedAtUnixMs], + ["uint64", deadlineUnixMs], + ["uint8", status], + ["bytes32", nonce] + ]); +} + +export function finalityReceiptId({ + receiptId, + reportId, + challengeRoot, + finalityState, + finalizedAtUnixMs, + finalizedBlockNumber, + finalizedBlockHash, + policyHash +}) { + return typedHash(TYPE_STRINGS.finalityReceiptV0, [ + ["bytes32", receiptId], + ["bytes32", reportId], + ["bytes32", challengeRoot], + ["uint8", finalityState], + ["uint64", finalizedAtUnixMs], + ["uint64", finalizedBlockNumber], + ["bytes32", finalizedBlockHash], + ["bytes32", policyHash] + ]); +} + +export function hardwareSignalEnvelopeId({ + deviceId, + signalRoot, + previousSignalEnvelopeId, + channelRoot, + sequence, + observedAtUnixMs, + transport, + nonce +}) { + return typedHash(TYPE_STRINGS.hardwareSignalEnvelopeV0, [ + ["bytes32", deviceId], + ["bytes32", signalRoot], + ["bytes32", previousSignalEnvelopeId], + ["bytes32", channelRoot], + ["uint64", sequence], + ["uint64", observedAtUnixMs], + ["uint8", transport], + ["bytes32", nonce] + ]); +} + +export function controlPlaneProvenanceResponseId({ + requestId, + subjectId, + agentId, + receiptId, + reportId, + memoryCellId, + dependencyRoot, + responseBodyHash, + issuedAtUnixMs, + responseVersion +}) { + return typedHash(TYPE_STRINGS.controlPlaneProvenanceResponseV0, [ + ["bytes32", requestId], + ["bytes32", subjectId], + ["bytes32", agentId], + ["bytes32", receiptId], + ["bytes32", reportId], + ["bytes32", memoryCellId], + ["bytes32", dependencyRoot], + ["bytes32", responseBodyHash], + ["uint64", issuedAtUnixMs], + ["uint16", responseVersion] + ]); +} + +export function localSignatureEnvelopeHash({ + objectId, + objectTypeHash, + domainSeparator, + signerId, + signerKeyId, + signerRole, + sequence, + issuedAtUnixMs, + expiresAtUnixMs, + nonce +}) { + return typedHash(TYPE_STRINGS.localSignatureEnvelopeV0, [ + ["bytes32", objectId], + ["bytes32", objectTypeHash], + ["bytes32", domainSeparator], + ["bytes32", signerId], + ["bytes32", signerKeyId], + ["uint8", signerRole], + ["uint64", sequence], + ["uint64", issuedAtUnixMs], + ["uint64", expiresAtUnixMs], + ["bytes32", nonce] + ]); +} + +export const localSignatureEnvelopeId = localSignatureEnvelopeHash; + +export function localSignatureEnvelopePayload(input) { + const structHash = localSignatureEnvelopeHash(input); + return { + structHash, + signingDigest: eip712Digest(input.domainSeparator, structHash) + }; +} + +export function localAlphaObjectTypeHash(objectSchema) { + return keccakUtf8(objectSchema); +} + +export const LOCAL_ALPHA_OBJECT_DESCRIPTORS = Object.freeze({ + "flowchain.agent_account.v0": { + objectType: "agent_account", + idField: "agentId", + domainName: "agentAccountId", + signerRoles: ["operator"], + nonzeroFields: [ + "agentId", + "namespaceId", + "policyRoot", + "toolPermissionsRoot", + "modelAllowlistRoot", + "memoryNamespaceRoot", + "nonce" + ], + input: (document) => ({ + namespaceId: document.namespaceId, + owner: document.owner, + policyRoot: document.policyRoot, + toolPermissionsRoot: document.toolPermissionsRoot, + modelAllowlistRoot: document.modelAllowlistRoot, + memoryNamespaceRoot: document.memoryNamespaceRoot, + spendingLimitPerEpoch: document.spendingLimitPerEpoch, + nonce: document.nonce + }), + id: agentAccountId + }, + "flowchain.model_passport.v0": { + objectType: "model_passport", + idField: "modelId", + domainName: "modelPassportId", + signerRoles: ["operator"], + nonzeroFields: [ + "modelId", + "providerHash", + "modelFamilyHash", + "versionHash", + "licenseRoot", + "policyRoot", + "artifactRoot", + "metadataHash", + "nonce" + ], + input: (document) => ({ + providerHash: document.providerHash, + modelFamilyHash: document.modelFamilyHash, + versionHash: document.versionHash, + licenseRoot: document.licenseRoot, + policyRoot: document.policyRoot, + artifactRoot: document.artifactRoot, + metadataHash: document.metadataHash, + nonce: document.nonce + }), + id: modelPassportId + }, + "flowchain.work_receipt.v0": { + objectType: "work_receipt", + idField: "workReceiptId", + domainName: "workReceiptId", + signerRoles: ["agent"], + nonzeroFields: ["workReceiptId", "observationId", "receiptHash", "workerId", "nonce"], + input: (document) => ({ + observationId: document.observationId, + receiptHash: document.receiptHash, + workerId: document.workerId, + workerSequence: document.workerSequence, + nonce: document.nonce + }), + id: workReceiptId + }, + "flowchain.artifact_availability_proof.v0": { + objectType: "artifact_availability_proof", + idField: "proofId", + domainName: "artifactAvailabilityProofId", + signerRoles: ["operator"], + nonzeroFields: [ + "proofId", + "artifactRoot", + "providerId", + "locationCommitment", + "storageReceiptCommitment", + "availabilitySampleRoot", + "nonce" + ], + input: (document) => ({ + artifactRoot: document.artifactRoot, + providerId: document.providerId, + locationCommitment: document.locationCommitment, + storageReceiptCommitment: document.storageReceiptCommitment, + availabilitySampleRoot: document.availabilitySampleRoot, + issuedAtUnixMs: document.issuedAtUnixMs, + expiresAtUnixMs: document.expiresAtUnixMs, + status: document.statusCode, + nonce: document.nonce + }), + id: artifactAvailabilityProofId + }, + "flowchain.verifier_module.v0": { + objectType: "verifier_module", + idField: "moduleId", + domainName: "verifierModuleId", + signerRoles: ["verifier", "operator"], + nonzeroFields: [ + "moduleId", + "ownerId", + "codeRoot", + "manifestRoot", + "supportedModesRoot", + "supportedChallengeTypesRoot", + "verifierSetRoot" + ], + input: (document) => ({ + ownerId: document.ownerId, + codeRoot: document.codeRoot, + manifestRoot: document.manifestRoot, + supportedModesRoot: document.supportedModesRoot, + supportedChallengeTypesRoot: document.supportedChallengeTypesRoot, + verifierSetRoot: document.verifierSetRoot, + moduleVersion: document.moduleVersion, + status: document.statusCode + }), + id: verifierModuleId + }, + "flowchain.verifier_report.v0": { + objectType: "verifier_report", + idField: "reportId", + domainName: "verifierReportDigest", + signerRoles: ["verifier"], + nonzeroFields: [ + "reportId", + "reportSchemaHash", + "observationId", + "receiptHash", + "verifierId", + "verifierSetRoot", + "checksRoot", + "finalizedBlockHash" + ], + input: (document) => ({ + reportSchemaHash: document.reportSchemaHash, + observationId: document.observationId, + receiptHash: document.receiptHash, + verifierId: document.verifierId, + verifierSetRoot: document.verifierSetRoot, + status: document.statusCode, + checksRoot: document.checksRoot, + finalizedBlockNumber: document.finalizedBlockNumber, + finalizedBlockHash: document.finalizedBlockHash, + reportVersion: document.reportVersion + }), + id: verifierReportHash + }, + "flowchain.memory_cell.v0": { + objectType: "memory_cell", + idField: "memoryCellId", + domainName: "memoryCellId", + signerRoles: ["agent"], + dependencyField: "dependencyRoot", + nonzeroFields: [ + "memoryCellId", + "ownerAgentId", + "currentMemoryRoot", + "lastDeltaRoot", + "sourceReceiptsRoot", + "dependencyRoot" + ], + input: (document) => ({ + ownerAgentId: document.ownerAgentId, + currentMemoryRoot: document.currentMemoryRoot, + previousMemoryRoot: document.previousMemoryRoot, + lastDeltaRoot: document.lastDeltaRoot, + sourceReceiptsRoot: document.sourceReceiptsRoot, + dependencyRoot: document.dependencyRoot, + updatedAtUnixMs: document.updatedAtUnixMs, + cellVersion: document.cellVersion + }), + id: memoryCellId, + parentRootCheck(document) { + return document.currentMemoryRoot !== ZERO_BYTES32 && document.currentMemoryRoot !== document.previousMemoryRoot; + } + }, + "flowchain.challenge.v0": { + objectType: "challenge", + idField: "challengeId", + domainName: "challengeId", + signerRoles: ["agent", "operator"], + nonzeroFields: ["challengeId", "receiptId", "challengerId", "evidenceRoot", "nonce"], + input: (document) => ({ + receiptId: document.receiptId, + challengerId: document.challengerId, + challengeType: document.challengeTypeCode, + evidenceRoot: document.evidenceRoot, + openedAtUnixMs: document.openedAtUnixMs, + deadlineUnixMs: document.deadlineUnixMs, + status: document.statusCode, + nonce: document.nonce + }), + id: challengeId + }, + "flowchain.finality_receipt.v0": { + objectType: "finality_receipt", + idField: "finalityReceiptId", + domainName: "finalityReceiptId", + signerRoles: ["verifier"], + nonzeroFields: ["finalityReceiptId", "receiptId", "reportId", "challengeRoot", "policyHash"], + input: (document) => ({ + receiptId: document.receiptId, + reportId: document.reportId, + challengeRoot: document.challengeRoot, + finalityState: document.finalityStateCode, + finalizedAtUnixMs: document.finalizedAtUnixMs, + finalizedBlockNumber: document.finalizedBlockNumber, + finalizedBlockHash: document.finalizedBlockHash, + policyHash: document.policyHash + }), + id: finalityReceiptId, + parentRootCheck(document) { + if (document.finalityStateCode !== LOCAL_ALPHA_FINALITY_STATES.finalized) { + return true; + } + return ( + document.finalizedAtUnixMs !== "0" && + document.finalizedBlockNumber !== "0" && + document.finalizedBlockHash !== ZERO_BYTES32 + ); + } + }, + "flowchain.hardware_signal_envelope.v0": { + objectType: "hardware_signal_envelope", + idField: "hardwareSignalEnvelopeId", + domainName: "hardwareSignalEnvelopeId", + signerRoles: ["hardware"], + nonzeroFields: ["hardwareSignalEnvelopeId", "deviceId", "signalRoot", "channelRoot", "nonce"], + input: (document) => ({ + deviceId: document.deviceId, + signalRoot: document.signalRoot, + previousSignalEnvelopeId: document.previousSignalEnvelopeId, + channelRoot: document.channelRoot, + sequence: document.sequence, + observedAtUnixMs: document.observedAtUnixMs, + transport: document.transportCode, + nonce: document.nonce + }), + id: hardwareSignalEnvelopeId, + parentRootCheck(document) { + return document.previousSignalEnvelopeId !== document.hardwareSignalEnvelopeId; + } + }, + "flowchain.control_plane_provenance_response.v0": { + objectType: "control_plane_provenance_response", + idField: "provenanceResponseId", + domainName: "controlPlaneProvenanceResponseId", + signerRoles: ["operator", "agent"], + dependencyField: "dependencyRoot", + nonzeroFields: [ + "provenanceResponseId", + "requestId", + "subjectId", + "agentId", + "receiptId", + "reportId", + "memoryCellId", + "dependencyRoot", + "responseBodyHash" + ], + input: (document) => ({ + requestId: document.requestId, + subjectId: document.subjectId, + agentId: document.agentId, + receiptId: document.receiptId, + reportId: document.reportId, + memoryCellId: document.memoryCellId, + dependencyRoot: document.dependencyRoot, + responseBodyHash: document.responseBodyHash, + issuedAtUnixMs: document.issuedAtUnixMs, + responseVersion: document.responseVersion + }), + id: controlPlaneProvenanceResponseId + } +}); + +export function localAlphaObjectDescriptor(objectSchema) { + return LOCAL_ALPHA_OBJECT_DESCRIPTORS[objectSchema]; +} + +export function localAlphaObjectInput(document) { + const descriptor = localAlphaObjectDescriptor(document?.schema); + if (!descriptor) { + throw new Error(`unknown local alpha object schema: ${document?.schema}`); + } + return descriptor.input(document); +} + +export function localAlphaObjectId(document) { + const descriptor = localAlphaObjectDescriptor(document?.schema); + if (!descriptor) { + throw new Error(`unknown local alpha object schema: ${document?.schema}`); + } + return descriptor.id(descriptor.input(document)); +} + +export function localAlphaEnvelopeReplayKey(envelope) { + return `${envelope.signerId}:${envelope.domain}:${envelope.sequence}`; +} + +export function localSignatureEnvelopeInput(envelope) { + return { + objectId: envelope.objectId, + objectTypeHash: envelope.objectTypeHash, + domainSeparator: envelope.domainSeparator, + signerId: envelope.signerId, + signerKeyId: envelope.signerKeyId, + signerRole: envelope.signerRoleCode, + sequence: envelope.sequence, + issuedAtUnixMs: envelope.issuedAtUnixMs, + expiresAtUnixMs: envelope.expiresAtUnixMs, + nonce: envelope.nonce + }; +} + +export function validateLocalAlphaEnvelope({ document, envelope, context = {} }) { + const errors = []; + const descriptor = localAlphaObjectDescriptor(document?.schema); + + if (!descriptor) { + errors.push("wrong-object-type"); + return { valid: false, errors }; + } + + if (!envelope || typeof envelope !== "object") { + errors.push("missing-signer"); + return { valid: false, errors }; + } + + const expectedObjectTypeHash = localAlphaObjectTypeHash(document.schema); + const expectedDomain = DOMAIN_STRINGS[descriptor.domainName]; + const expectedDomainSeparator = domainSeparator(descriptor.domainName); + + if (envelope.objectSchema !== document.schema || envelope.objectType !== descriptor.objectType) { + errors.push("wrong-object-type"); + } + if (envelope.objectTypeHash !== expectedObjectTypeHash) { + errors.push("wrong-object-type"); + } + if (envelope.domain !== expectedDomain || envelope.domainSeparator !== expectedDomainSeparator) { + errors.push("wrong-domain"); + } + + const idField = descriptor.idField; + if (!isHex32(document[idField]) || !isHex32(envelope.objectId) || !isHex32(envelope.envelopeId)) { + errors.push("malformed-id"); + } + + for (const field of descriptor.nonzeroFields ?? []) { + if (document[field] === ZERO_BYTES32 || envelope.objectId === ZERO_BYTES32) { + errors.push("zero-hash"); + break; + } + } + + if (descriptor.dependencyField) { + const dependency = document[descriptor.dependencyField]; + if (!isHex32(dependency) || dependency === ZERO_BYTES32) { + errors.push("malformed-dependency"); + } + } + + if (descriptor.parentRootCheck && !descriptor.parentRootCheck(document)) { + errors.push("bad-parent-root"); + } + + try { + const expectedObjectId = localAlphaObjectId(document); + if (document[idField] !== expectedObjectId || envelope.objectId !== expectedObjectId) { + errors.push("bad-object-id"); + } + } catch (error) { + errors.push(classifyObjectError(error)); + } + + const signerRoleCode = LOCAL_ALPHA_SIGNER_ROLES[envelope.signerRole]; + const signerMissing = + !envelope.signerId || + !envelope.signerKeyId || + !envelope.publicKey || + !envelope.signature || + envelope.signerId === ZERO_BYTES32 || + envelope.signerKeyId === ZERO_BYTES32 || + signerRoleCode === undefined || + signerRoleCode !== envelope.signerRoleCode || + !descriptor.signerRoles.includes(envelope.signerRole); + + if (signerMissing) { + errors.push("missing-signer"); + } + + const seenSequences = context.seenSequences; + if (seenSequences?.has?.(localAlphaEnvelopeReplayKey(envelope))) { + errors.push("replay"); + } + + try { + const envelopeInput = localSignatureEnvelopeInput(envelope); + const expectedEnvelopeId = localSignatureEnvelopeHash(envelopeInput); + const expectedPayload = localSignatureEnvelopePayload(envelopeInput); + if (envelope.envelopeId !== expectedEnvelopeId) { + errors.push("bad-envelope-id"); + } + if (envelope.signingDigest !== expectedPayload.signingDigest) { + errors.push("bad-envelope-digest"); + } + if ( + envelope.signature && + envelope.publicKey && + !verifyDigest({ + digest: envelope.signingDigest, + signature: envelope.signature, + publicKey: envelope.publicKey + }) + ) { + errors.push("bad-signature"); + } + } catch (error) { + errors.push(classifyObjectError(error)); + } + + return { + valid: errors.length === 0, + errors: [...new Set(errors)] + }; +} + +function isHex32(value) { + if (typeof value !== "string") { + return false; + } + try { + hexToBytes(value, 32); + return true; + } catch { + return false; + } +} + +function classifyObjectError(error) { + if (/hex|bytes/i.test(String(error?.message))) { + return "malformed-id"; + } + return "invalid-object"; +} diff --git a/crypto/src/validate-local-alpha-fixtures.js b/crypto/src/validate-local-alpha-fixtures.js new file mode 100644 index 00000000..92f481ed --- /dev/null +++ b/crypto/src/validate-local-alpha-fixtures.js @@ -0,0 +1,61 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +import Ajv2020 from "ajv/dist/2020.js"; +import addFormats from "ajv-formats"; + +const defaultFixturePath = resolve(import.meta.dirname, "..", "fixtures", "local-alpha-objects.json"); + +export function validateLocalAlphaFixtures(fixturePath = defaultFixturePath) { + const fixture = readJson(fixturePath); + assert.equal(fixture.schema, "flowmemory.crypto.local-alpha-object-fixtures.v0"); + + const fixtureDir = resolve(fixturePath, ".."); + const ajv = new Ajv2020({ allErrors: true, strict: false }); + addFormats(ajv); + + const validators = new Map(); + const validateDocument = (schemaPath, document, label) => { + const absoluteSchemaPath = resolve(fixtureDir, schemaPath); + let validate = validators.get(absoluteSchemaPath); + if (!validate) { + validate = ajv.compile(readJson(absoluteSchemaPath)); + validators.set(absoluteSchemaPath, validate); + } + + if (!validate(document)) { + throw new Error(`${label} failed schema validation: ${ajv.errorsText(validate.errors)}`); + } + }; + + let documentCount = 0; + for (const vector of fixture.positive) { + validateDocument(vector.schemaPath, vector.document, vector.name); + documentCount += 1; + } + + let envelopeCount = 0; + for (const vector of fixture.envelopes.positive) { + validateDocument(vector.schemaPath, vector.envelope, vector.name); + envelopeCount += 1; + } + + return { + documents: documentCount, + envelopes: envelopeCount, + schemas: validators.size + }; +} + +function readJson(path) { + return JSON.parse(readFileSync(path, "utf8")); +} + +if (fileURLToPath(import.meta.url) === resolve(process.argv[1])) { + const result = validateLocalAlphaFixtures(process.argv[2]); + console.log( + `FLOWCHAIN_LOCAL_ALPHA_FIXTURES_OK documents=${result.documents} envelopes=${result.envelopes} schemas=${result.schemas}` + ); +} diff --git a/crypto/src/validate-vectors.js b/crypto/src/validate-vectors.js index b2e65358..9701e472 100644 --- a/crypto/src/validate-vectors.js +++ b/crypto/src/validate-vectors.js @@ -5,22 +5,32 @@ import { fileURLToPath } from "node:url"; import { artifactFromChunks, + agentAccountId, + artifactAvailabilityProofId, attestationEnvelopeHash, + challengeId, canonicalJsonHash, + controlPlaneProvenanceResponseId, contractPulseId, devnetBlockHash, domainSeparator, emptyMerkleRoot, + finalityReceiptId, flowPulseEventArgsHash, flowPulseObservationId, flowPulseSchemaId, + hardwareSignalEnvelopeId, indexerCursorId, + localSignatureEnvelopeHash, + memoryCellId, merkleLeafHash, merkleRoot, + modelPassportId, receiptHash, rootCommitment, rootfieldNamespaceId, storageReceiptCommitmentHash, + verifierModuleId, verifierIdentity, verifierReportHash, workReceiptId, @@ -29,22 +39,32 @@ import { const validators = Object.freeze({ artifactFromChunks, + agentAccountId, + artifactAvailabilityProofId, attestationEnvelopeHash, + challengeId, canonicalJsonHash, + controlPlaneProvenanceResponseId, contractPulseId, devnetBlockHash, domainSeparator: ({ domainName }) => domainSeparator(domainName), emptyMerkleRoot, + finalityReceiptId, flowPulseEventArgsHash, flowPulseObservationId, flowPulseSchemaId, + hardwareSignalEnvelopeId, indexerCursorId, + localSignatureEnvelopeHash, + memoryCellId, merkleLeafHash, merkleRoot: ({ leaves }) => merkleRoot(leaves), + modelPassportId, receiptHash, rootCommitment, rootfieldNamespaceId, storageReceiptCommitmentHash, + verifierModuleId, verifierIdentity, verifierReportHash, workReceiptId, diff --git a/crypto/test/crypto.test.js b/crypto/test/crypto.test.js index 13b9ec2f..63f524ff 100644 --- a/crypto/test/crypto.test.js +++ b/crypto/test/crypto.test.js @@ -5,23 +5,37 @@ import test from "node:test"; import { artifactFromChunks, + agentAccountId, + artifactAvailabilityProofId, attestationEnvelopeHash, + challengeId, canonicalJsonHash, canonicalJson, + controlPlaneProvenanceResponseId, contractPulseId, cursorId, devnetBlockHash, + DOMAIN_STRINGS, domainSeparator, eip712DomainSeparator, emptyMerkleRoot, + finalityReceiptId, flowPulseEventArgsHash, flowPulseEventSignature, flowPulseObservationId, flowPulseSchemaId, + hardwareSignalEnvelopeId, indexerCursorId, + localAlphaEnvelopeReplayKey, + localAlphaObjectId, + localSignatureEnvelopeHash, + localSignatureEnvelopeInput, + localSignatureEnvelopePayload, keccakUtf8, + memoryCellId, merkleLeafHash, merkleRoot, + modelPassportId, normalizeHex, publicKeyFromPrivateKey, receiptHash, @@ -29,6 +43,10 @@ import { rootfieldNamespaceId, signDigest, storageReceiptCommitmentHash, + TYPE_STRINGS, + typedHash, + validateLocalAlphaEnvelope, + verifierModuleId, verifierIdentity, verifierReportHash, verifierSignaturePayload, @@ -37,6 +55,7 @@ import { workerIdentity, workerSignaturePayload } from "../src/index.js"; +import { validateLocalAlphaFixtures } from "../src/validate-local-alpha-fixtures.js"; import { validateVectors } from "../src/validate-vectors.js"; const root = resolve(import.meta.dirname, ".."); @@ -48,6 +67,71 @@ function fixture(name) { const flowPulse = fixture("sample-flowpulse.json"); const observation = fixture("sample-observation.json"); const report = fixture("sample-report.json"); +const localAlphaObjects = fixture("local-alpha-objects.json"); + +const localAlphaValidators = Object.freeze({ + agentAccountId, + artifactAvailabilityProofId, + challengeId, + controlPlaneProvenanceResponseId, + finalityReceiptId, + hardwareSignalEnvelopeId, + localSignatureEnvelopeHash, + memoryCellId, + modelPassportId, + verifierModuleId, + verifierReportHash, + workReceiptId +}); + +function assertSchemaDocument(schemaPath, document) { + const schema = JSON.parse(readFileSync(resolve(root, "fixtures", schemaPath), "utf8")); + assert.equal(document.schema, schema.properties.schema.const); + assert.deepEqual( + Object.keys(document).sort(), + Object.keys(schema.properties).sort(), + `${document.schema} should not drift from its schema properties` + ); + + for (const key of schema.required) { + assert.ok(Object.hasOwn(document, key), `${document.schema} missing ${key}`); + } + + for (const [key, definition] of Object.entries(schema.properties)) { + const value = document[key]; + const resolved = definition.$ref + ? schema.$defs[definition.$ref.replace("#/$defs/", "")] + : definition; + if (resolved.const !== undefined) { + assert.equal(value, resolved.const, `${document.schema}.${key}`); + } + if (resolved.pattern) { + assert.match(value, new RegExp(resolved.pattern), `${document.schema}.${key}`); + } + if (resolved.enum) { + assert.ok(resolved.enum.includes(value), `${document.schema}.${key}`); + } + if (resolved.type === "integer") { + assert.equal(Number.isInteger(value), true, `${document.schema}.${key}`); + } + if (resolved.type === "object") { + assert.equal(value !== null && typeof value === "object" && !Array.isArray(value), true); + } + } +} + +function assertNoDuplicateObjectIds(documents) { + const seen = new Set(); + for (const document of documents) { + const idKey = Object.keys(document).find((key) => key.endsWith("Id")); + assert.ok(idKey, `${document.schema} should expose an id field`); + const id = document[idKey]; + if (seen.has(id)) { + throw new Error(`duplicate object id: ${id}`); + } + seen.add(id); + } +} test("canonicalJson sorts object keys recursively", () => { assert.equal(canonicalJson({ b: 2, a: { d: 4, c: 3 } }), '{"a":{"c":3,"d":4},"b":2}'); @@ -247,8 +331,130 @@ test("receipt-adjacent fields fail closed when changed", () => { assert.notEqual(wrongVerifierSet.signingDigest, report.verifierSignature.expected.signingDigest); }); +test("computes FlowChain Local Alpha object ids and validates schema documents", () => { + assert.equal(localAlphaObjects.schema, "flowmemory.crypto.local-alpha-object-fixtures.v0"); + assert.match(localAlphaObjects.rdBoundary.researchCryptoCrate, /noesis-crypto$/); + assert.match(localAlphaObjects.rdBoundary.consumeAs, /Research vocabulary/); + assert.match(localAlphaObjects.rdBoundary.operatorVaultBoundary, /no-value test keys/); + + for (const vector of localAlphaObjects.positive) { + const fn = localAlphaValidators[vector.function]; + assert.ok(fn, `unknown local alpha object function: ${vector.function}`); + assert.equal(fn(vector.input), vector.expected, vector.name); + assert.equal(vector.document[vector.idField], vector.expected, `${vector.name} document id`); + assert.equal(localAlphaObjectId(vector.document), vector.expected, `${vector.name} recomputed document id`); + assertSchemaDocument(vector.schemaPath, vector.document); + } +}); + +test("validates FlowChain Local Alpha signed object envelopes", () => { + const documentsByName = new Map(localAlphaObjects.positive.map((entry) => [entry.name, entry.document])); + const seenSequences = new Set(); + + for (const vector of localAlphaObjects.envelopes.positive) { + const document = documentsByName.get(vector.objectName); + assert.ok(document, `unknown envelope object: ${vector.objectName}`); + assertSchemaDocument(vector.schemaPath, vector.envelope); + assert.equal(localSignatureEnvelopeHash(vector.input), vector.expected.envelopeId, vector.name); + assert.deepEqual(localSignatureEnvelopePayload(vector.input), { + structHash: vector.expected.envelopeId, + signingDigest: vector.expected.signingDigest + }); + assert.deepEqual(localSignatureEnvelopeInput(vector.envelope), vector.input); + + const result = validateLocalAlphaEnvelope({ + document, + envelope: vector.envelope, + context: { seenSequences } + }); + assert.deepEqual(result, { valid: true, errors: [] }, vector.name); + seenSequences.add(localAlphaEnvelopeReplayKey(vector.envelope)); + } +}); + +test("AJV validates all Local Alpha object and envelope fixtures against canonical schemas", () => { + assert.deepEqual(validateLocalAlphaFixtures(), { + documents: 11, + envelopes: 11, + schemas: 12 + }); +}); + +test("Local Alpha signed envelope vectors reject replay, wrong domains, missing signer, malformed roots, and wrong types", () => { + const documentsByName = new Map(localAlphaObjects.positive.map((entry) => [entry.name, entry.document])); + const envelopesByName = new Map(localAlphaObjects.envelopes.positive.map((entry) => [entry.name, entry])); + + for (const vector of localAlphaObjects.envelopes.negative) { + const { document, envelope, context } = mutatedEnvelopeVector(vector, documentsByName, envelopesByName); + const result = validateLocalAlphaEnvelope({ document, envelope, context }); + assert.equal(result.valid, false, vector.name); + for (const expectedError of vector.expectErrors) { + assert.ok( + result.errors.includes(expectedError), + `${vector.name} expected ${expectedError}, got ${result.errors.join(", ")}` + ); + } + } +}); + +test("Local Alpha object fixtures reject swapped fields, malformed hex, duplicate ids, and changed type strings", () => { + for (const negative of localAlphaObjects.negative) { + if (negative.reason === "swapped-field-rejection") { + const fn = localAlphaValidators[negative.function]; + assert.notEqual(fn(negative.input), negative.mustNotEqual, negative.name); + } + if (negative.reason === "malformed-hex-rejection") { + const fn = localAlphaValidators[negative.function]; + assert.throws(() => fn(negative.input), /invalid hex/, negative.name); + } + if (negative.reason === "duplicate-id-rejection") { + assert.throws(() => assertNoDuplicateObjectIds(negative.documents), /duplicate object id/, negative.name); + } + } + + const modelPassport = localAlphaObjects.positive.find((entry) => entry.function === "modelPassportId"); + const changedTypeString = TYPE_STRINGS.modelPassportV0.replace( + "FlowChainModelPassportV0", + "FlowChainModelPassportV1" + ); + const changedTypeHash = typedHash(changedTypeString, [ + ["bytes32", modelPassport.input.providerHash], + ["bytes32", modelPassport.input.modelFamilyHash], + ["bytes32", modelPassport.input.versionHash], + ["bytes32", modelPassport.input.licenseRoot], + ["bytes32", modelPassport.input.policyRoot], + ["bytes32", modelPassport.input.artifactRoot], + ["bytes32", modelPassport.input.metadataHash], + ["bytes32", modelPassport.input.nonce] + ]); + + assert.notEqual(changedTypeHash, modelPassport.expected); + assert.notEqual( + domainSeparator("modelPassportId"), + domainSeparator("flowchain.local-alpha.v1.model-passport.id") + ); +}); + +test("control-plane provenance response uses stable canonical JSON body hashing", () => { + const provenance = localAlphaObjects.positive.find( + (entry) => entry.function === "controlPlaneProvenanceResponseId" + ); + const shuffledBody = { + limitations: [ + "V0 binds IDs and commitments only.", + "V0 does not prove model output correctness." + ], + status: "challengeable", + subject: "local-alpha-memory-cell" + }; + + assert.equal(canonicalJsonHash(shuffledBody), provenance.input.responseBodyHash); + assert.equal(canonicalJsonHash(provenance.document.responseBody), provenance.document.responseBodyHash); + assert.equal(controlPlaneProvenanceResponseId(provenance.input), provenance.expected); +}); + test("validates all published crypto test vectors", () => { - assert.equal(validateVectors(), 21); + assert.equal(validateVectors(), 33); }); test("signs and verifies verifier digests with local test keys only", async () => { @@ -264,3 +470,38 @@ test("signs and verifies verifier digests with local test keys only", async () = assert.equal(verifyDigest({ digest, signature, publicKey: wrongPublicKey }), false); assert.equal(verifyDigest({ digest: wrongDigest, signature, publicKey }), false); }); + +function mutatedEnvelopeVector(vector, documentsByName, envelopesByName) { + const base = envelopesByName.get(vector.baseEnvelope); + assert.ok(base, `unknown base envelope: ${vector.baseEnvelope}`); + const document = structuredClone(documentsByName.get(base.objectName)); + const envelope = structuredClone(base.envelope); + const mutation = vector.mutation ?? {}; + + if (mutation.document) { + Object.assign(document, mutation.document); + } + if (mutation.documentFromDocumentField) { + for (const [target, source] of Object.entries(mutation.documentFromDocumentField)) { + document[target] = document[source]; + } + } + if (mutation.envelope) { + const { domainFrom, ...envelopeFields } = mutation.envelope; + Object.assign(envelope, envelopeFields); + if (domainFrom) { + envelope.domain = DOMAIN_STRINGS[domainFrom]; + envelope.domainSeparator = domainSeparator(domainFrom); + } + } + for (const field of mutation.deleteEnvelopeFields ?? []) { + delete envelope[field]; + } + + const context = {}; + if (mutation.contextReplay) { + context.seenSequences = new Set([localAlphaEnvelopeReplayKey(envelope)]); + } + + return { document, envelope, context }; +} diff --git a/research/cryptography/FLOWCHAIN_RD_GATES.md b/research/cryptography/FLOWCHAIN_RD_GATES.md new file mode 100644 index 00000000..87b5f95f --- /dev/null +++ b/research/cryptography/FLOWCHAIN_RD_GATES.md @@ -0,0 +1,29 @@ +# FlowChain Cryptography RD Gates + +Status: boundary document for Local Alpha. + +The current `crypto/` package defines Keccak typed IDs, schemas, fixtures, and +local signature-envelope validation. It does not implement production proof +systems or audited cryptography. + +## Gated Tracks + +| Track | Gate Before Implementation Or Claim | +| --- | --- | +| Process-Witness | Accepted public inputs, witness format, replay policy, privacy boundary, and cross-language vectors. | +| SEAL/dependency privacy | Dependency atom schema, disclosure policy, verifier checks, challenge behavior, and dashboard status vocabulary. | +| Synthetic Non-Amplification | Formal rule, fixture corpus, verifier module behavior, invalid vectors, and review decision. | +| Advanced encrypted compute | Threat model, key lifecycle, leakage policy, deterministic verifier boundary, and failure reporting. | +| GPU proofs | Proof system choice, public inputs, cost model, verifier module ID, local vectors, and reproducible proof fixtures. | +| Audited production proof systems | Named audit artifact, merged decision record, issue acceptance, verifier enforcement path, and production go/no-go record. | + +## Current Boundary + +- Use `crypto/fixtures/local-alpha-objects.json` for Local Alpha object and + envelope vectors. +- Use `schemas/flowmemory/` for local/test JSON document shape. +- Treat nearby RD crates as research inputs only unless a compatibility adapter + and matching vectors are accepted. +- Do not claim full trustlessness, production L1 readiness, storage permanence, + model-output correctness, encrypted-compute security, GPU proof security, or + audit coverage from the current package. diff --git a/research/cryptography/IMPLEMENTATION_PLAN.md b/research/cryptography/IMPLEMENTATION_PLAN.md index 86faa6c3..bc4c7cc0 100644 --- a/research/cryptography/IMPLEMENTATION_PLAN.md +++ b/research/cryptography/IMPLEMENTATION_PLAN.md @@ -26,7 +26,7 @@ Acceptance checks: ## Phase 1: Test Vector Harness -Status: runnable package candidate exists in `crypto/` with 21 package-level vectors and a Python FlowPulse aggregate cross-check. +Status: runnable package candidate exists in `crypto/` with 33 package-level vectors, Local Alpha object and signed-envelope fixtures, schema-backed validation tests, and a Python FlowPulse aggregate cross-check. Deliverables: @@ -34,12 +34,16 @@ Deliverables: - Validate `crypto/test-vectors/flowpulse-observation-v0.json`. - Add negative tests for swapped fields, changed type strings, wrong Merkle order, and odd-leaf handling. - Add equivalent vectors for empty artifact and one-chunk artifact roots. +- Add canonical Local Alpha vectors for AgentAccount, ModelPassport, WorkReceipt, ArtifactAvailabilityProof, VerifierModule, VerifierReport, MemoryCell, Challenge, FinalityReceipt, hardware signal envelopes, and control-plane provenance responses. +- Add local operator, agent, verifier, and hardware signature-envelope vectors and invalid vectors for replay, wrong domain, missing signer, bad signature, zero hash, malformed id, malformed dependency, bad parent/root, and wrong object type. Acceptance checks: - Local tests reproduce all vector hashes. - Bad vectors fail deterministically. - No production keys, secrets, RPC URLs, or private locators are committed. +- The RD/research crypto boundary is explicit: nearby Noesis/FlowChain SHA-256 and proof-system scaffolds are research inputs, while FlowMemory `crypto/` remains the Keccak typed-hash package for Local Alpha. +- Deferred RD tracks are gated in `research/cryptography/FLOWCHAIN_RD_GATES.md`: Process-Witness, SEAL/dependency privacy, Synthetic Non-Amplification, advanced encrypted compute, GPU proofs, and audited production proof systems. ## Phase 2: Shared Contract Hash Library diff --git a/schemas/flowmemory/README.md b/schemas/flowmemory/README.md index d3650385..db096054 100644 --- a/schemas/flowmemory/README.md +++ b/schemas/flowmemory/README.md @@ -7,6 +7,18 @@ These schemas are the canonical local/test V0 shapes for generated Flow Memory a - `rootflow-transition.schema.json` - `rootfield-bundle.schema.json` - `agent-memory-view.schema.json` +- `agent-account.schema.json` +- `model-passport.schema.json` +- `work-receipt.schema.json` +- `memory-cell.schema.json` +- `artifact-availability-proof.schema.json` +- `verifier-module.schema.json` +- `verifier-report.schema.json` +- `challenge.schema.json` +- `finality-receipt.schema.json` +- `hardware-signal-envelope.schema.json` +- `local-signature-envelope.schema.json` +- `control-plane-provenance-response.schema.json` `memory-signal.schema.json` also embeds the `flowmemory.flowpulse_contract_event.v0` shape, which records the `IFlowPulse.FlowPulse` event signature, indexed fields, @@ -14,3 +26,21 @@ payload fields, and receipt-derived locator fields that the indexer added after reading logs and receipts. They describe local fixture objects only. They do not claim production L1 readiness, trustless verification, free storage, AI running on-chain, or production Uniswap v4 deployment. + +The `flowchain.*.v0` schemas describe Local Alpha object documents whose IDs +are defined in `crypto/src/objects.js` and pinned by +`crypto/fixtures/local-alpha-objects.json`. They map the research object names +from the Noesis/FlowChain corpus into the current FlowMemory crypto package +without importing research-only SHA-256 or proof-system scaffolds. + +`local-signature-envelope.schema.json` describes the local/test operator, +agent, verifier, and hardware signature envelope that wraps these object IDs. +The schema is paired with the validator in `crypto/src/objects.js`; consumers +should validate both JSON shape and recomputed cryptographic fields. + +Run the canonical Local Alpha schema/fixture check from the crypto package: + +```powershell +cd E:\FlowMemory\flowmemory-crypto\crypto +npm run validate:local-alpha +``` diff --git a/schemas/flowmemory/agent-account.schema.json b/schemas/flowmemory/agent-account.schema.json new file mode 100644 index 00000000..3e169acf --- /dev/null +++ b/schemas/flowmemory/agent-account.schema.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.agent_account.v0", + "title": "FlowChain Local Alpha AgentAccount V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "agentId", + "namespaceId", + "owner", + "policyRoot", + "toolPermissionsRoot", + "modelAllowlistRoot", + "memoryNamespaceRoot", + "spendingLimitPerEpoch", + "status", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.agent_account.v0" }, + "agentId": { "$ref": "#/$defs/hex32" }, + "namespaceId": { "$ref": "#/$defs/hex32" }, + "owner": { "$ref": "#/$defs/address" }, + "policyRoot": { "$ref": "#/$defs/hex32" }, + "toolPermissionsRoot": { "$ref": "#/$defs/hex32" }, + "modelAllowlistRoot": { "$ref": "#/$defs/hex32" }, + "memoryNamespaceRoot": { "$ref": "#/$defs/hex32" }, + "spendingLimitPerEpoch": { "$ref": "#/$defs/uintString" }, + "status": { "enum": ["draft", "active", "paused", "revoked"] }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "address": { "type": "string", "pattern": "^0x[0-9a-fA-F]{40}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/artifact-availability-proof.schema.json b/schemas/flowmemory/artifact-availability-proof.schema.json new file mode 100644 index 00000000..e99d5779 --- /dev/null +++ b/schemas/flowmemory/artifact-availability-proof.schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.artifact_availability_proof.v0", + "title": "FlowChain Local Alpha ArtifactAvailabilityProof V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "proofId", + "artifactRoot", + "providerId", + "locationCommitment", + "storageReceiptCommitment", + "availabilitySampleRoot", + "issuedAtUnixMs", + "expiresAtUnixMs", + "status", + "statusCode", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.artifact_availability_proof.v0" }, + "proofId": { "$ref": "#/$defs/hex32" }, + "artifactRoot": { "$ref": "#/$defs/hex32" }, + "providerId": { "$ref": "#/$defs/hex32" }, + "locationCommitment": { "$ref": "#/$defs/hex32" }, + "storageReceiptCommitment": { "$ref": "#/$defs/hex32" }, + "availabilitySampleRoot": { "$ref": "#/$defs/hex32" }, + "issuedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "expiresAtUnixMs": { "$ref": "#/$defs/uintString" }, + "status": { "enum": ["draft", "available", "unavailable", "expired"] }, + "statusCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/challenge.schema.json b/schemas/flowmemory/challenge.schema.json new file mode 100644 index 00000000..7d1d58b1 --- /dev/null +++ b/schemas/flowmemory/challenge.schema.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.challenge.v0", + "title": "FlowChain Local Alpha Challenge V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "challengeId", + "receiptId", + "challengerId", + "challengeType", + "challengeTypeCode", + "evidenceRoot", + "openedAtUnixMs", + "deadlineUnixMs", + "status", + "statusCode", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.challenge.v0" }, + "challengeId": { "$ref": "#/$defs/hex32" }, + "receiptId": { "$ref": "#/$defs/hex32" }, + "challengerId": { "$ref": "#/$defs/hex32" }, + "challengeType": { + "enum": [ + "missing_artifact", + "invalid_artifact_root", + "missing_model_passport", + "memory_parent_mismatch", + "policy_violation", + "deterministic_replay_failure", + "dependency_omission" + ] + }, + "challengeTypeCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "evidenceRoot": { "$ref": "#/$defs/hex32" }, + "openedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "deadlineUnixMs": { "$ref": "#/$defs/uintString" }, + "status": { "enum": ["open", "submitter_wins", "challenger_wins", "unresolved", "expired"] }, + "statusCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/control-plane-provenance-response.schema.json b/schemas/flowmemory/control-plane-provenance-response.schema.json new file mode 100644 index 00000000..a1a2127a --- /dev/null +++ b/schemas/flowmemory/control-plane-provenance-response.schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.control_plane_provenance_response.v0", + "title": "FlowChain Local Alpha Control-Plane Provenance Response V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "provenanceResponseId", + "requestId", + "subjectId", + "agentId", + "receiptId", + "reportId", + "memoryCellId", + "dependencyRoot", + "responseBodyHash", + "responseBody", + "issuedAtUnixMs", + "responseVersion" + ], + "properties": { + "schema": { "const": "flowchain.control_plane_provenance_response.v0" }, + "provenanceResponseId": { "$ref": "#/$defs/hex32" }, + "requestId": { "$ref": "#/$defs/hex32" }, + "subjectId": { "$ref": "#/$defs/hex32" }, + "agentId": { "$ref": "#/$defs/hex32" }, + "receiptId": { "$ref": "#/$defs/hex32" }, + "reportId": { "$ref": "#/$defs/hex32" }, + "memoryCellId": { "$ref": "#/$defs/hex32" }, + "dependencyRoot": { "$ref": "#/$defs/hex32" }, + "responseBodyHash": { "$ref": "#/$defs/hex32" }, + "responseBody": { + "type": "object", + "additionalProperties": true + }, + "issuedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "responseVersion": { "type": "integer", "minimum": 0, "maximum": 65535 } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/finality-receipt.schema.json b/schemas/flowmemory/finality-receipt.schema.json new file mode 100644 index 00000000..e96c4cd7 --- /dev/null +++ b/schemas/flowmemory/finality-receipt.schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.finality_receipt.v0", + "title": "FlowChain Local Alpha FinalityReceipt V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "finalityReceiptId", + "receiptId", + "reportId", + "challengeRoot", + "finalityState", + "finalityStateCode", + "finalizedAtUnixMs", + "finalizedBlockNumber", + "finalizedBlockHash", + "policyHash" + ], + "properties": { + "schema": { "const": "flowchain.finality_receipt.v0" }, + "finalityReceiptId": { "$ref": "#/$defs/hex32" }, + "receiptId": { "$ref": "#/$defs/hex32" }, + "reportId": { "$ref": "#/$defs/hex32" }, + "challengeRoot": { "$ref": "#/$defs/hex32" }, + "finalityState": { + "enum": ["provisional", "challengeable", "challenged", "accepted", "rejected", "finalized", "superseded", "reorged"] + }, + "finalityStateCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "finalizedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "finalizedBlockNumber": { "$ref": "#/$defs/uintString" }, + "finalizedBlockHash": { "$ref": "#/$defs/hex32" }, + "policyHash": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/hardware-signal-envelope.schema.json b/schemas/flowmemory/hardware-signal-envelope.schema.json new file mode 100644 index 00000000..fa15e0dc --- /dev/null +++ b/schemas/flowmemory/hardware-signal-envelope.schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.hardware_signal_envelope.v0", + "title": "FlowChain Local Alpha HardwareSignalEnvelope V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "hardwareSignalEnvelopeId", + "deviceId", + "signalRoot", + "previousSignalEnvelopeId", + "channelRoot", + "sequence", + "observedAtUnixMs", + "transport", + "transportCode", + "status", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.hardware_signal_envelope.v0" }, + "hardwareSignalEnvelopeId": { "$ref": "#/$defs/hex32" }, + "deviceId": { "$ref": "#/$defs/hex32" }, + "signalRoot": { "$ref": "#/$defs/hex32" }, + "previousSignalEnvelopeId": { "$ref": "#/$defs/hex32" }, + "channelRoot": { "$ref": "#/$defs/hex32" }, + "sequence": { "$ref": "#/$defs/uintString" }, + "observedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "transport": { "enum": ["local_simulator", "usb_serial", "lora_control", "meshtastic_control"] }, + "transportCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "status": { "enum": ["observed", "accepted", "rejected", "replayed"] }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/local-signature-envelope.schema.json b/schemas/flowmemory/local-signature-envelope.schema.json new file mode 100644 index 00000000..04a6be0a --- /dev/null +++ b/schemas/flowmemory/local-signature-envelope.schema.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.local_signature_envelope.v0", + "title": "FlowChain Local Alpha LocalSignatureEnvelope V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "envelopeId", + "objectType", + "objectSchema", + "objectId", + "objectTypeHash", + "domain", + "domainSeparator", + "signerRole", + "signerRoleCode", + "signerId", + "signerKeyId", + "publicKey", + "sequence", + "issuedAtUnixMs", + "expiresAtUnixMs", + "nonce", + "signingDigest", + "signature" + ], + "properties": { + "schema": { "const": "flowchain.local_signature_envelope.v0" }, + "envelopeId": { "$ref": "#/$defs/hex32" }, + "objectType": { + "enum": [ + "agent_account", + "model_passport", + "work_receipt", + "artifact_availability_proof", + "verifier_module", + "verifier_report", + "memory_cell", + "challenge", + "finality_receipt", + "hardware_signal_envelope", + "control_plane_provenance_response" + ] + }, + "objectSchema": { "type": "string", "pattern": "^flowchain\\.[a-z_]+\\.v0$" }, + "objectId": { "$ref": "#/$defs/hex32" }, + "objectTypeHash": { "$ref": "#/$defs/hex32" }, + "domain": { "type": "string", "pattern": "^(flowchain\\.local-alpha\\.v0|flowmemory\\.v0)\\.[a-z0-9.-]+$" }, + "domainSeparator": { "$ref": "#/$defs/hex32" }, + "signerRole": { "enum": ["operator", "agent", "verifier", "hardware"] }, + "signerRoleCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "signerId": { "$ref": "#/$defs/hex32" }, + "signerKeyId": { "$ref": "#/$defs/hex32" }, + "publicKey": { "type": "string", "pattern": "^0x([0-9a-fA-F]{66}|[0-9a-fA-F]{130})$" }, + "sequence": { "$ref": "#/$defs/uintString" }, + "issuedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "expiresAtUnixMs": { "$ref": "#/$defs/uintString" }, + "nonce": { "$ref": "#/$defs/hex32" }, + "signingDigest": { "$ref": "#/$defs/hex32" }, + "signature": { "type": "string", "pattern": "^0x[0-9a-fA-F]{128}$" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/memory-cell.schema.json b/schemas/flowmemory/memory-cell.schema.json new file mode 100644 index 00000000..35b5b878 --- /dev/null +++ b/schemas/flowmemory/memory-cell.schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.memory_cell.v0", + "title": "FlowChain Local Alpha MemoryCell V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "memoryCellId", + "ownerAgentId", + "currentMemoryRoot", + "previousMemoryRoot", + "lastDeltaRoot", + "sourceReceiptsRoot", + "dependencyRoot", + "status", + "updatedAtUnixMs", + "cellVersion" + ], + "properties": { + "schema": { "const": "flowchain.memory_cell.v0" }, + "memoryCellId": { "$ref": "#/$defs/hex32" }, + "ownerAgentId": { "$ref": "#/$defs/hex32" }, + "currentMemoryRoot": { "$ref": "#/$defs/hex32" }, + "previousMemoryRoot": { "$ref": "#/$defs/hex32" }, + "lastDeltaRoot": { "$ref": "#/$defs/hex32" }, + "sourceReceiptsRoot": { "$ref": "#/$defs/hex32" }, + "dependencyRoot": { "$ref": "#/$defs/hex32" }, + "status": { "enum": ["active", "frozen", "superseded", "reorged"] }, + "updatedAtUnixMs": { "$ref": "#/$defs/uintString" }, + "cellVersion": { "type": "integer", "minimum": 0, "maximum": 65535 } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/model-passport.schema.json b/schemas/flowmemory/model-passport.schema.json new file mode 100644 index 00000000..48eb4e96 --- /dev/null +++ b/schemas/flowmemory/model-passport.schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.model_passport.v0", + "title": "FlowChain Local Alpha ModelPassport V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "modelId", + "providerHash", + "modelFamilyHash", + "versionHash", + "licenseRoot", + "policyRoot", + "artifactRoot", + "metadataHash", + "status", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.model_passport.v0" }, + "modelId": { "$ref": "#/$defs/hex32" }, + "providerHash": { "$ref": "#/$defs/hex32" }, + "modelFamilyHash": { "$ref": "#/$defs/hex32" }, + "versionHash": { "$ref": "#/$defs/hex32" }, + "licenseRoot": { "$ref": "#/$defs/hex32" }, + "policyRoot": { "$ref": "#/$defs/hex32" }, + "artifactRoot": { "$ref": "#/$defs/hex32" }, + "metadataHash": { "$ref": "#/$defs/hex32" }, + "status": { "enum": ["draft", "active", "deprecated", "rejected"] }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" } + } +} diff --git a/schemas/flowmemory/verifier-module.schema.json b/schemas/flowmemory/verifier-module.schema.json new file mode 100644 index 00000000..0611806f --- /dev/null +++ b/schemas/flowmemory/verifier-module.schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.verifier_module.v0", + "title": "FlowChain Local Alpha VerifierModule V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "moduleId", + "ownerId", + "codeRoot", + "manifestRoot", + "supportedModesRoot", + "supportedChallengeTypesRoot", + "verifierSetRoot", + "moduleVersion", + "status", + "statusCode" + ], + "properties": { + "schema": { "const": "flowchain.verifier_module.v0" }, + "moduleId": { "$ref": "#/$defs/hex32" }, + "ownerId": { "$ref": "#/$defs/hex32" }, + "codeRoot": { "$ref": "#/$defs/hex32" }, + "manifestRoot": { "$ref": "#/$defs/hex32" }, + "supportedModesRoot": { "$ref": "#/$defs/hex32" }, + "supportedChallengeTypesRoot": { "$ref": "#/$defs/hex32" }, + "verifierSetRoot": { "$ref": "#/$defs/hex32" }, + "moduleVersion": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "status": { "enum": ["draft", "active", "paused", "revoked"] }, + "statusCode": { "type": "integer", "minimum": 1, "maximum": 255 } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" } + } +} diff --git a/schemas/flowmemory/verifier-report.schema.json b/schemas/flowmemory/verifier-report.schema.json new file mode 100644 index 00000000..a68eafdf --- /dev/null +++ b/schemas/flowmemory/verifier-report.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.verifier_report.v0", + "title": "FlowChain Local Alpha VerifierReport V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "reportId", + "reportSchemaHash", + "observationId", + "receiptHash", + "verifierId", + "verifierSetRoot", + "status", + "statusCode", + "checksRoot", + "finalizedBlockNumber", + "finalizedBlockHash", + "reportVersion" + ], + "properties": { + "schema": { "const": "flowchain.verifier_report.v0" }, + "reportId": { "$ref": "#/$defs/hex32" }, + "reportSchemaHash": { "$ref": "#/$defs/hex32" }, + "observationId": { "$ref": "#/$defs/hex32" }, + "receiptHash": { "$ref": "#/$defs/hex32" }, + "verifierId": { "$ref": "#/$defs/hex32" }, + "verifierSetRoot": { "$ref": "#/$defs/hex32" }, + "status": { "enum": ["observed", "verified", "unresolved", "unsupported", "failed", "reorged", "superseded"] }, + "statusCode": { "type": "integer", "minimum": 1, "maximum": 255 }, + "checksRoot": { "$ref": "#/$defs/hex32" }, + "finalizedBlockNumber": { "$ref": "#/$defs/uintString" }, + "finalizedBlockHash": { "$ref": "#/$defs/hex32" }, + "reportVersion": { "type": "integer", "minimum": 0, "maximum": 65535 } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +} diff --git a/schemas/flowmemory/work-receipt.schema.json b/schemas/flowmemory/work-receipt.schema.json new file mode 100644 index 00000000..de0e8a14 --- /dev/null +++ b/schemas/flowmemory/work-receipt.schema.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "flowchain.work_receipt.v0", + "title": "FlowChain Local Alpha WorkReceipt V0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "workReceiptId", + "observationId", + "receiptHash", + "workerId", + "workerSequence", + "status", + "nonce" + ], + "properties": { + "schema": { "const": "flowchain.work_receipt.v0" }, + "workReceiptId": { "$ref": "#/$defs/hex32" }, + "observationId": { "$ref": "#/$defs/hex32" }, + "receiptHash": { "$ref": "#/$defs/hex32" }, + "workerId": { "$ref": "#/$defs/hex32" }, + "workerSequence": { "$ref": "#/$defs/uintString" }, + "status": { "enum": ["observed", "pending", "verified", "failed", "reorged"] }, + "nonce": { "$ref": "#/$defs/hex32" } + }, + "$defs": { + "hex32": { "type": "string", "pattern": "^0x[0-9a-fA-F]{64}$" }, + "uintString": { "type": "string", "pattern": "^[0-9]+$" } + } +}