@motebit/state-export-client 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -57,6 +57,29 @@ if (inner.applicable && !inner.allValid) {
57
57
 
58
58
  `verifyInnerSignedReceipts` returns `applicable: false` for v1.0 bodies, non-execution-ledger bodies, or bodies with an empty `signed_receipts` field — calm-software default, no flag required. On v1.1 bodies, every entry is parsed, every signature is checked against its embedded public key, and `delegation_receipts` chains are walked recursively.
59
59
 
60
+ ## Quick start — verify a pasted receipt (receipt.computer)
61
+
62
+ ```ts
63
+ import { verifyReceiptDocument } from "@motebit/state-export-client";
64
+
65
+ const v = await verifyReceiptDocument(pastedJsonText);
66
+
67
+ if (v.binding === "revoked") {
68
+ show(`Key revoked — do not trust (revoked at ${new Date(v.revokedAt!).toISOString()})`);
69
+ } else if (!v.integrity) {
70
+ show(`Verification failed: ${v.reason}`); // malformed_json | not_a_receipt | signature_invalid | …
71
+ } else if (v.binding === "anchored" || v.binding === "pinned") {
72
+ show(`Verified — from ${v.motebitId}`); // key bound to the motebit (anchored adds on-chain non-equivocation)
73
+ } else {
74
+ // integrity-only: signature is valid but checked against the receipt's OWN
75
+ // embedded key — proves the bytes weren't tampered, NOT that the key belongs
76
+ // to motebitId. Never render "from <motebit>" here.
77
+ show("Signature verified — identity not anchored");
78
+ }
79
+ ```
80
+
81
+ `verifyReceiptDocument` is the brain behind a public, login-free receipt verifier. It runs entirely offline (no relay) for the integrity check, never throws on bad input (typed `reason`s instead), and keeps **integrity** (the bytes were signed, untampered) strictly separate from **binding** (the key belongs to this `motebitId`). The binding ladder: `integrity-only` (no options) < `pinned` (pass `options.identity` — the key is time-valid in the motebit's own succession chain) < `anchored` (also pass `options.anchor` — the binding is in the relay's transparency log AND that root is independently confirmed on-chain). Never render "from &lt;motebit&gt;" below `pinned`. `revoked` is off the ladder — a poison verdict: pass `options.revocation` and if the signing key has an on-chain revocation memo dated at/before the receipt, `binding` is `revoked` regardless of everything else (read from the neutral chain, never the relay's word).
82
+
60
83
  ## Trust-anchor chain
61
84
 
62
85
  ```
@@ -91,19 +114,37 @@ if (lookup.ok) {
91
114
  }
92
115
  ```
93
116
 
117
+ The same on-chain channel raises a receipt's binding to `anchored`. The relay's `/identity/:motebitId` bundle carries a transparency-log inclusion proof and the tx that posted its root; `lookupIdentityLogAnchor` confirms that root really sits on-chain at the relay's **pinned** address (passed out-of-band, never from the bundle). Wire it through `verifyReceiptDocument`:
118
+
119
+ ```ts
120
+ import { lookupIdentityLogAnchor, verifyReceiptDocument } from "@motebit/state-export-client";
121
+
122
+ const v = await verifyReceiptDocument(pastedJsonText, {
123
+ identity, // the motebit's identity file (reaches `pinned`)
124
+ anchor: {
125
+ proof: bundle.anchored.proof, // from GET /api/v1/identity/:motebitId
126
+ relayAnchorAddress: PINNED_RELAY_SOLANA_ADDRESS, // out-of-band trust root
127
+ },
128
+ });
129
+ // v.binding === "anchored" only when inclusion AND the on-chain root cross-check both pass.
130
+ ```
131
+
94
132
  ## Programmatic surface
95
133
 
96
- | Export | Kind | Role |
97
- | ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
98
- | `fetchTransparencyAnchor(baseUrl, opts?)` | function | TOFU bootstrap — fetch `/.well-known/motebit-transparency.json`, verify self-signature, return pinned `TransparencyAnchor` |
99
- | `verifyTransparencyDeclaration(declaration)` | function | Lower-level: verify a `SignedTransparencyDeclaration` from any source (cached, archived, fixture) |
100
- | `verifiedStateExportFetch(url, opts)` | function | Wrap `fetch` — verify outer envelope against body bytes + optional anchor pin |
101
- | `verifyManifestAgainstBytes(manifest, bodyBytes, anchor?)` | function | Lower-level: verify a parsed `ContentArtifactManifest` against bytes you already have |
102
- | `verifyInnerSignedReceipts(body)` | function | Recursive v1.1 inner-receipt audit — per-receipt verdict with typed failure reasons |
103
- | `lookupTransparencyAnchor(opts)` | function | Onchain query Solana RPC for a Memo program transaction posting the declaration hash |
104
- | `verifyDeclarationOnchainAnchor(declaration, anchor)` | function | Onchain — verify the Memo transaction's signer and content match the declaration |
105
- | `StateExportFetchError` | class | Thrown on non-2xx HTTP; verifier never attempts to verify error envelopes |
106
- | `MANIFEST_HEADER` | constant | The header name (`"X-Motebit-Content-Manifest"`) exposed for custom transports |
134
+ | Export | Kind | Role |
135
+ | ---------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
136
+ | `fetchTransparencyAnchor(baseUrl, opts?)` | function | TOFU bootstrap — fetch `/.well-known/motebit-transparency.json`, verify self-signature, return pinned `TransparencyAnchor` |
137
+ | `verifyTransparencyDeclaration(declaration)` | function | Lower-level: verify a `SignedTransparencyDeclaration` from any source (cached, archived, fixture) |
138
+ | `verifiedStateExportFetch(url, opts)` | function | Wrap `fetch` — verify outer envelope against body bytes + optional anchor pin |
139
+ | `verifyManifestAgainstBytes(manifest, bodyBytes, anchor?)` | function | Lower-level: verify a parsed `ContentArtifactManifest` against bytes you already have |
140
+ | `verifyInnerSignedReceipts(body)` | function | Recursive v1.1 inner-receipt audit — per-receipt verdict with typed failure reasons |
141
+ | `verifyReceiptDocument(jsonText)` | function | Verify a pasted/standalone receipt offline honest view model separating integrity from identity binding (powers receipt.computer) |
142
+ | `lookupTransparencyAnchor(opts)` | function | Onchain — query Solana RPC for a Memo program transaction posting the declaration hash |
143
+ | `verifyDeclarationOnchainAnchor(declaration, anchor)` | function | Onchain verify the Memo transaction's signer and content match the declaration |
144
+ | `lookupIdentityLogAnchor(address, root, opts?)` | function | Onchain confirm a transparency-log root sits on-chain at the pinned relay address (the `anchored` binding rung) |
145
+ | `lookupKeyRevocation(address, keyHex, opts?)` | function | Onchain — find a `motebit:revocation:v1:` memo revoking a signing key (the `revoked` poison verdict; read from the chain, not the relay) |
146
+ | `StateExportFetchError` | class | Thrown on non-2xx HTTP; verifier never attempts to verify error envelopes |
147
+ | `MANIFEST_HEADER` | constant | The header name (`"X-Motebit-Content-Manifest"`) — exposed for custom transports |
107
148
 
108
149
  All result types (`TransparencyAnchorResult`, `StateExportVerification`, `InnerReceiptsVerification`, etc.) and failure-reason unions are also exported — discriminated unions, type-narrowable by the `ok` / `valid` / `applicable` field.
109
150
 
@@ -0,0 +1,63 @@
1
+ /**
2
+ * On-chain cross-check for the identity-transparency log root.
3
+ *
4
+ * The relay's `/identity` bundle carries a Merkle inclusion proof against an
5
+ * `anchoredRoot` it claims to have posted on-chain. `@motebit/crypto`'s
6
+ * `verifyIdentityBindingAnchored` proves the leaf is included under that root —
7
+ * but nothing stops a relay from fabricating a root it never anchored. This
8
+ * module closes that gap the same way `lookupTransparencyAnchor` closes the TOFU
9
+ * gap on the transparency declaration: scan the relay's pinned Solana address for
10
+ * a memo that actually carries that exact root.
11
+ *
12
+ * The relay anchors identity-log roots through the generic `ChainAnchorSubmitter`
13
+ * memo (`motebit:anchor:v1:{root}:{leafCount}`), shared with settlement and
14
+ * credential anchoring. Matching by the EXACT root value is sound across that
15
+ * shared stream: identity-binding leaves hash `{type:"motebit-identity-binding",
16
+ * …}`, so a root over them is domain-separated from any settlement/credential
17
+ * root and cannot collide. We don't need a dedicated memo prefix — only the root.
18
+ *
19
+ * The pinned `relayAnchorAddress` is the trust root: it MUST come from out-of-band
20
+ * (canonical config / docs site / a known motebit-org keyring), NEVER from the
21
+ * bundle itself — passing the relay's self-asserted address would be circular
22
+ * trust, the same caveat the transparency anchor carries.
23
+ *
24
+ * No SDK dep — Solana JSON-RPC is plain HTTP-JSON over `fetch`, keeping the
25
+ * package browser-safe and dep-thin. Mirrors `onchain-anchor.ts`.
26
+ */
27
+ export interface IdentityAnchorLookupOptions {
28
+ /** Solana JSON-RPC endpoint. Defaults to mainnet-beta; pin a known-good RPC. */
29
+ readonly rpcUrl?: string;
30
+ /** Inject `fetch`. Defaults to global `fetch`; tests pass a mock. */
31
+ readonly fetch?: typeof globalThis.fetch;
32
+ /**
33
+ * Max signatures to scan at the anchor address. Identity-log anchors share the
34
+ * address with settlement/credential anchors, so the target root may be several
35
+ * memos back; default 200 covers a generous window of recent anchoring.
36
+ */
37
+ readonly maxSignatures?: number;
38
+ }
39
+ export type IdentityAnchorResult = {
40
+ readonly ok: true;
41
+ readonly txHash: string;
42
+ readonly anchoredRoot: string;
43
+ readonly relayAnchorAddress: string;
44
+ } | {
45
+ readonly ok: false;
46
+ readonly reason: IdentityAnchorFailureReason;
47
+ readonly detail?: string;
48
+ };
49
+ export type IdentityAnchorFailureReason = "rpc_failed" | "root_not_anchored";
50
+ /**
51
+ * Confirm `expectedRootHex` was posted on-chain by the relay at
52
+ * `relayAnchorAddress`. Returns a typed result — never throws on verification
53
+ * failure; HTTP/transport errors surface as `rpc_failed`. A clean
54
+ * `root_not_anchored` means the scan completed but no `motebit:anchor` memo at the
55
+ * address carried that root (either never anchored, or beyond the scan window).
56
+ *
57
+ * The caller is expected to run this AFTER `verifyIdentityBindingAnchored` has
58
+ * confirmed the leaf is included under `expectedRootHex` — this adds the second
59
+ * trust channel (the root is really on-chain by the known relay) on top of the
60
+ * inclusion proof; it does not replace it.
61
+ */
62
+ export declare function lookupIdentityLogAnchor(relayAnchorAddress: string, expectedRootHex: string, options?: IdentityAnchorLookupOptions): Promise<IdentityAnchorResult>;
63
+ //# sourceMappingURL=identity-anchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-anchor.d.ts","sourceRoot":"","sources":["../src/identity-anchor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,MAAM,WAAW,2BAA2B;IAC1C,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC,GACD;IACE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEN,MAAM,MAAM,2BAA2B,GAAG,YAAY,GAAG,mBAAmB,CAAC;AAiB7E;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,MAAM,EACvB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,oBAAoB,CAAC,CAyD/B"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * On-chain cross-check for the identity-transparency log root.
3
+ *
4
+ * The relay's `/identity` bundle carries a Merkle inclusion proof against an
5
+ * `anchoredRoot` it claims to have posted on-chain. `@motebit/crypto`'s
6
+ * `verifyIdentityBindingAnchored` proves the leaf is included under that root —
7
+ * but nothing stops a relay from fabricating a root it never anchored. This
8
+ * module closes that gap the same way `lookupTransparencyAnchor` closes the TOFU
9
+ * gap on the transparency declaration: scan the relay's pinned Solana address for
10
+ * a memo that actually carries that exact root.
11
+ *
12
+ * The relay anchors identity-log roots through the generic `ChainAnchorSubmitter`
13
+ * memo (`motebit:anchor:v1:{root}:{leafCount}`), shared with settlement and
14
+ * credential anchoring. Matching by the EXACT root value is sound across that
15
+ * shared stream: identity-binding leaves hash `{type:"motebit-identity-binding",
16
+ * …}`, so a root over them is domain-separated from any settlement/credential
17
+ * root and cannot collide. We don't need a dedicated memo prefix — only the root.
18
+ *
19
+ * The pinned `relayAnchorAddress` is the trust root: it MUST come from out-of-band
20
+ * (canonical config / docs site / a known motebit-org keyring), NEVER from the
21
+ * bundle itself — passing the relay's self-asserted address would be circular
22
+ * trust, the same caveat the transparency anchor carries.
23
+ *
24
+ * No SDK dep — Solana JSON-RPC is plain HTTP-JSON over `fetch`, keeping the
25
+ * package browser-safe and dep-thin. Mirrors `onchain-anchor.ts`.
26
+ */
27
+ /** The generic anchor-memo prefix the relay's ChainAnchorSubmitter emits. */
28
+ const ANCHOR_MEMO_PREFIX = "motebit:anchor:v1:";
29
+ /**
30
+ * Confirm `expectedRootHex` was posted on-chain by the relay at
31
+ * `relayAnchorAddress`. Returns a typed result — never throws on verification
32
+ * failure; HTTP/transport errors surface as `rpc_failed`. A clean
33
+ * `root_not_anchored` means the scan completed but no `motebit:anchor` memo at the
34
+ * address carried that root (either never anchored, or beyond the scan window).
35
+ *
36
+ * The caller is expected to run this AFTER `verifyIdentityBindingAnchored` has
37
+ * confirmed the leaf is included under `expectedRootHex` — this adds the second
38
+ * trust channel (the root is really on-chain by the known relay) on top of the
39
+ * inclusion proof; it does not replace it.
40
+ */
41
+ export async function lookupIdentityLogAnchor(relayAnchorAddress, expectedRootHex, options = {}) {
42
+ const rpcUrl = options.rpcUrl ?? "https://api.mainnet-beta.solana.com";
43
+ const fetchImpl = options.fetch ?? globalThis.fetch;
44
+ const limit = options.maxSignatures ?? 200;
45
+ const target = expectedRootHex.toLowerCase();
46
+ let signatures;
47
+ try {
48
+ const res = await fetchImpl(rpcUrl, {
49
+ method: "POST",
50
+ headers: { "Content-Type": "application/json" },
51
+ body: JSON.stringify({
52
+ jsonrpc: "2.0",
53
+ id: 1,
54
+ method: "getSignaturesForAddress",
55
+ params: [relayAnchorAddress, { limit }],
56
+ }),
57
+ });
58
+ if (!res.ok) {
59
+ return { ok: false, reason: "rpc_failed", detail: `HTTP ${res.status}` };
60
+ }
61
+ const body = (await res.json());
62
+ if (body.error !== undefined) {
63
+ return { ok: false, reason: "rpc_failed", detail: body.error.message };
64
+ }
65
+ signatures = body.result ?? [];
66
+ }
67
+ catch (err) {
68
+ return {
69
+ ok: false,
70
+ reason: "rpc_failed",
71
+ detail: err instanceof Error ? err.message : String(err),
72
+ };
73
+ }
74
+ for (const sig of signatures) {
75
+ if (sig.err !== null)
76
+ continue; // skip failed txs
77
+ if (sig.memo == null)
78
+ continue;
79
+ // Solana RPC formats memo as `[<size> (len <bytes>)] <utf-8>`; match the
80
+ // canonical prefix anywhere in the formatted string (robust across RPC
81
+ // versions), then read the 64-hex root that immediately follows it.
82
+ const idx = sig.memo.indexOf(ANCHOR_MEMO_PREFIX);
83
+ if (idx === -1)
84
+ continue;
85
+ const after = sig.memo.slice(idx + ANCHOR_MEMO_PREFIX.length);
86
+ const rootMatch = after.match(/^([0-9a-fA-F]{64})/);
87
+ if (rootMatch == null)
88
+ continue;
89
+ if (rootMatch[1].toLowerCase() === target) {
90
+ return { ok: true, txHash: sig.signature, anchoredRoot: target, relayAnchorAddress };
91
+ }
92
+ }
93
+ return {
94
+ ok: false,
95
+ reason: "root_not_anchored",
96
+ detail: `scanned ${signatures.length} signature(s) at ${relayAnchorAddress}, none carried root ${target}`,
97
+ };
98
+ }
99
+ //# sourceMappingURL=identity-anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-anchor.js","sourceRoot":"","sources":["../src/identity-anchor.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -48,6 +48,12 @@ export { verifiedStateExportFetch, verifyManifestAgainstBytes, StateExportFetchE
48
48
  export type { StateExportVerification, StateExportVerificationFailureReason, VerifiedFetchOptions, VerifiedStateExportResponse, } from "./verified-fetch.js";
49
49
  export { lookupTransparencyAnchor, verifyDeclarationOnchainAnchor } from "./onchain-anchor.js";
50
50
  export type { OnchainAnchorLookupOptions, OnchainAnchorResult, OnchainAnchorFailureReason, } from "./onchain-anchor.js";
51
+ export { lookupIdentityLogAnchor } from "./identity-anchor.js";
52
+ export type { IdentityAnchorLookupOptions, IdentityAnchorResult, IdentityAnchorFailureReason, } from "./identity-anchor.js";
53
+ export { lookupKeyRevocation } from "./key-revocation.js";
54
+ export type { KeyRevocationLookupOptions, KeyRevocationResult } from "./key-revocation.js";
51
55
  export { verifyInnerSignedReceipts } from "./inner-receipts.js";
52
56
  export type { InnerReceiptVerification, InnerReceiptVerificationFailureReason, InnerReceiptsVerification, } from "./inner-receipts.js";
57
+ export { verifyReceiptDocument } from "./receipt-document.js";
58
+ export type { ReceiptDocumentVerification, ReceiptDocumentFailureReason, ReceiptBindingStatus, ReceiptAnchorOptions, VerifyReceiptDocumentOptions, } from "./receipt-document.js";
53
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,wBAAwB,EACxB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,uBAAuB,EACvB,oCAAoC,EACpC,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAC/F,YAAY,EACV,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EACV,wBAAwB,EACxB,qCAAqC,EACrC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,wBAAwB,EACxB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,uBAAuB,EACvB,oCAAoC,EACpC,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAC/F,YAAY,EACV,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EACV,2BAA2B,EAC3B,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,YAAY,EACV,wBAAwB,EACxB,qCAAqC,EACrC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -45,5 +45,8 @@
45
45
  export { fetchTransparencyAnchor, verifyTransparencyDeclaration } from "./transparency-anchor.js";
46
46
  export { verifiedStateExportFetch, verifyManifestAgainstBytes, StateExportFetchError, MANIFEST_HEADER, } from "./verified-fetch.js";
47
47
  export { lookupTransparencyAnchor, verifyDeclarationOnchainAnchor } from "./onchain-anchor.js";
48
+ export { lookupIdentityLogAnchor } from "./identity-anchor.js";
49
+ export { lookupKeyRevocation } from "./key-revocation.js";
48
50
  export { verifyInnerSignedReceipts } from "./inner-receipts.js";
51
+ export { verifyReceiptDocument } from "./receipt-document.js";
49
52
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AASlG,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAO/F,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AASlG,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAO/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAO/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAOhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -25,12 +25,28 @@
25
25
  export interface InnerReceiptVerification {
26
26
  /** Task identifier of the inner receipt. Pulled from the parsed receipt body. */
27
27
  readonly taskId: string;
28
- /** The producing motebit's identifier — what the relay claims; the signature proves it. */
28
+ /**
29
+ * The producing motebit's identifier as carried in the receipt body.
30
+ * NOTE: a valid signature proves the embedded key signed these bytes, NOT
31
+ * that the key belongs to this `motebitId` — see `identityBinding`.
32
+ */
29
33
  readonly motebitId: string;
30
34
  /** `did:key:zXXX` derived from the receipt's embedded public key when verification succeeded. */
31
35
  readonly signerDid?: string;
32
36
  /** Whether the inner receipt's signature verifies against its embedded `public_key`. */
33
37
  readonly valid: boolean;
38
+ /**
39
+ * Identity-binding status of a *successful* signature check. Always
40
+ * `"embedded-key-unverified"` on this path: the signature is checked
41
+ * against the receipt's own `public_key`, which proves byte-integrity but
42
+ * NOT that the key belongs to `motebitId`. Establishing binding requires
43
+ * an external anchor (the relay's pinned transparency key / a known-keys
44
+ * map). Callers MUST NOT render this as "from <motebit>" without an anchor
45
+ * — mirrors the content-artifact path's `producer_key_mismatch` discipline
46
+ * (see package CLAUDE.md "Why the trust anchor is necessary"). Absent on
47
+ * failures.
48
+ */
49
+ readonly identityBinding?: "embedded-key-unverified";
34
50
  /** Typed failure reason when `valid === false`. */
35
51
  readonly reason?: InnerReceiptVerificationFailureReason;
36
52
  /** Free-form detail (e.g. underlying error message). */
@@ -1 +1 @@
1
- {"version":3,"file":"inner-receipts.d.ts","sourceRoot":"","sources":["../src/inner-receipts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,uEAAuE;AACvE,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2FAA2F;IAC3F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,qCAAqC,CAAC;IACxD,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE,wBAAwB,EAAE,CAAC;CACnD;AAED,MAAM,MAAM,qCAAqC,GAC7C,gBAAgB,GAChB,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,SAAS,CAAC;AAEd,oFAAoF;AACpF,MAAM,WAAW,yBAAyB;IACxC,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,kGAAkG;IAClG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;IAC1D,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAkCjG"}
1
+ {"version":3,"file":"inner-receipts.d.ts","sourceRoot":"","sources":["../src/inner-receipts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,uEAAuE;AACvE,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,yBAAyB,CAAC;IACrD,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,qCAAqC,CAAC;IACxD,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE,wBAAwB,EAAE,CAAC;CACnD;AAED,MAAM,MAAM,qCAAqC,GAC7C,gBAAgB,GAChB,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,SAAS,CAAC;AAEd,oFAAoF;AACpF,MAAM,WAAW,yBAAyB;IACxC,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,kGAAkG;IAClG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;IAC1D,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAkCjG"}
@@ -96,6 +96,9 @@ async function verifyOneInner(entryJson) {
96
96
  motebitId: String(receipt.motebit_id),
97
97
  ...(result.signer !== undefined && { signerDid: result.signer }),
98
98
  valid: true,
99
+ ...(result.keySource === "embedded" && {
100
+ identityBinding: "embedded-key-unverified",
101
+ }),
99
102
  ...(result.delegations !== undefined && result.delegations.length > 0
100
103
  ? { delegations: result.delegations.map(toInnerShape) }
101
104
  : {}),
@@ -151,6 +154,8 @@ function toInnerShape(r) {
151
154
  motebitId: String(r.receipt?.motebit_id ?? "<unknown>"),
152
155
  ...(r.signer !== undefined && { signerDid: r.signer }),
153
156
  valid: r.valid,
157
+ ...(r.valid &&
158
+ r.keySource === "embedded" && { identityBinding: "embedded-key-unverified" }),
154
159
  ...(reason !== undefined && { reason }),
155
160
  ...(errs[0]?.message !== undefined && !r.valid && { detail: errs[0].message }),
156
161
  ...(r.delegations !== undefined && r.delegations.length > 0
@@ -1 +1 @@
1
- {"version":3,"file":"inner-receipts.js","sourceRoot":"","sources":["../src/inner-receipts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inner-receipts.js","sourceRoot":"","sources":["../src/inner-receipts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * On-chain key-revocation lookup — the binding-time consumer of the relay's
3
+ * revocation memos.
4
+ *
5
+ * When a key is rotated away or an agent is revoked, the relay anchors a
6
+ * `motebit:revocation:v1:{keyHex}:{timestamp}` memo on Solana
7
+ * (`SolanaMemoSubmitter.submitRevocation`). This module reads those memos so a
8
+ * verifier can refuse to bind a receipt signed by a key that was revoked at or
9
+ * before the receipt's timestamp.
10
+ *
11
+ * The trust asymmetry vs. the anchored rung is the whole point: a relay can't
12
+ * forge an anchored root, but it COULD hide a revocation that protects it (a key
13
+ * it secretly controls). So revocation must be read from the neutral chain at the
14
+ * relay's pinned address — never taken from the relay's own `/identity` response.
15
+ * `revoked_at` is whatever timestamp the memo carries; if the operator backdates
16
+ * it to the true compromise moment, this consumer honors that automatically.
17
+ *
18
+ * No SDK dep — Solana JSON-RPC over fetch keeps the package browser-safe. Mirrors
19
+ * `identity-anchor.ts` / `onchain-anchor.ts`.
20
+ */
21
+ export interface KeyRevocationLookupOptions {
22
+ readonly rpcUrl?: string;
23
+ readonly fetch?: typeof globalThis.fetch;
24
+ /** Max signatures to scan at the relay address. Default 200. */
25
+ readonly maxSignatures?: number;
26
+ }
27
+ export type KeyRevocationResult =
28
+ /** A revocation memo for this key was found on-chain. `revokedAt` is its timestamp (ms). */
29
+ {
30
+ readonly status: "revoked";
31
+ readonly revokedAt: number;
32
+ readonly txHash: string;
33
+ }
34
+ /** Scan completed; no revocation memo for this key at the address. */
35
+ | {
36
+ readonly status: "not_revoked";
37
+ }
38
+ /** Could not determine (RPC/transport failure) — NOT proof of safety. */
39
+ | {
40
+ readonly status: "unknown";
41
+ readonly detail: string;
42
+ };
43
+ /**
44
+ * Look up whether `signingKeyHex` has an on-chain revocation memo at the relay's
45
+ * pinned address. Returns the EARLIEST revocation timestamp found (the most
46
+ * protective — a key revoked at T cannot be trusted for anything dated ≥ T).
47
+ * Never throws; transport/RPC failures surface as `status: "unknown"`.
48
+ */
49
+ export declare function lookupKeyRevocation(relayAnchorAddress: string, signingKeyHex: string, options?: KeyRevocationLookupOptions): Promise<KeyRevocationResult>;
50
+ //# sourceMappingURL=key-revocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-revocation.d.ts","sourceRoot":"","sources":["../src/key-revocation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,mBAAmB;AAC7B,4FAA4F;AAC1F;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACrF,sEAAsE;GACpE;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE;AACpC,yEAAyE;GACvE;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAiB5D;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * On-chain key-revocation lookup — the binding-time consumer of the relay's
3
+ * revocation memos.
4
+ *
5
+ * When a key is rotated away or an agent is revoked, the relay anchors a
6
+ * `motebit:revocation:v1:{keyHex}:{timestamp}` memo on Solana
7
+ * (`SolanaMemoSubmitter.submitRevocation`). This module reads those memos so a
8
+ * verifier can refuse to bind a receipt signed by a key that was revoked at or
9
+ * before the receipt's timestamp.
10
+ *
11
+ * The trust asymmetry vs. the anchored rung is the whole point: a relay can't
12
+ * forge an anchored root, but it COULD hide a revocation that protects it (a key
13
+ * it secretly controls). So revocation must be read from the neutral chain at the
14
+ * relay's pinned address — never taken from the relay's own `/identity` response.
15
+ * `revoked_at` is whatever timestamp the memo carries; if the operator backdates
16
+ * it to the true compromise moment, this consumer honors that automatically.
17
+ *
18
+ * No SDK dep — Solana JSON-RPC over fetch keeps the package browser-safe. Mirrors
19
+ * `identity-anchor.ts` / `onchain-anchor.ts`.
20
+ */
21
+ const REVOCATION_MEMO_PREFIX = "motebit:revocation:v1:";
22
+ /**
23
+ * Look up whether `signingKeyHex` has an on-chain revocation memo at the relay's
24
+ * pinned address. Returns the EARLIEST revocation timestamp found (the most
25
+ * protective — a key revoked at T cannot be trusted for anything dated ≥ T).
26
+ * Never throws; transport/RPC failures surface as `status: "unknown"`.
27
+ */
28
+ export async function lookupKeyRevocation(relayAnchorAddress, signingKeyHex, options = {}) {
29
+ const rpcUrl = options.rpcUrl ?? "https://api.mainnet-beta.solana.com";
30
+ const fetchImpl = options.fetch ?? globalThis.fetch;
31
+ const limit = options.maxSignatures ?? 200;
32
+ const needle = `${REVOCATION_MEMO_PREFIX}${signingKeyHex.toLowerCase()}:`;
33
+ let signatures;
34
+ try {
35
+ const res = await fetchImpl(rpcUrl, {
36
+ method: "POST",
37
+ headers: { "Content-Type": "application/json" },
38
+ body: JSON.stringify({
39
+ jsonrpc: "2.0",
40
+ id: 1,
41
+ method: "getSignaturesForAddress",
42
+ params: [relayAnchorAddress, { limit }],
43
+ }),
44
+ });
45
+ if (!res.ok)
46
+ return { status: "unknown", detail: `HTTP ${res.status}` };
47
+ const body = (await res.json());
48
+ if (body.error !== undefined)
49
+ return { status: "unknown", detail: body.error.message };
50
+ signatures = body.result ?? [];
51
+ }
52
+ catch (err) {
53
+ return { status: "unknown", detail: err instanceof Error ? err.message : String(err) };
54
+ }
55
+ let earliest = null;
56
+ for (const sig of signatures) {
57
+ if (sig.err !== null)
58
+ continue;
59
+ if (sig.memo == null)
60
+ continue;
61
+ const idx = sig.memo.toLowerCase().indexOf(needle);
62
+ if (idx === -1)
63
+ continue;
64
+ const after = sig.memo.slice(idx + needle.length);
65
+ const tsMatch = after.match(/^(\d+)/);
66
+ if (tsMatch == null)
67
+ continue;
68
+ const revokedAt = Number(tsMatch[1]);
69
+ if (!Number.isFinite(revokedAt))
70
+ continue;
71
+ if (earliest == null || revokedAt < earliest.revokedAt) {
72
+ earliest = { revokedAt, txHash: sig.signature };
73
+ }
74
+ }
75
+ return earliest
76
+ ? { status: "revoked", revokedAt: earliest.revokedAt, txHash: earliest.txHash }
77
+ : { status: "not_revoked" };
78
+ }
79
+ //# sourceMappingURL=key-revocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-revocation.js","sourceRoot":"","sources":["../src/key-revocation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Verify a pasted/standalone `ExecutionReceipt` document and project it into an
3
+ * honest, display-ready view model — the brain behind a public receipt verifier
4
+ * (e.g. receipt.computer): paste a receipt, learn what it actually proves.
5
+ *
6
+ * The model's whole point is to keep two facts separate, the way the rest of the
7
+ * stack now does (crypto `keySource`, render-engine `bindingStatusFor`):
8
+ *
9
+ * - INTEGRITY — "the bytes were signed by *some* key and nothing was tampered."
10
+ * Always checkable offline from the receipt alone.
11
+ * - BINDING — "that key belongs to the claimed `motebit_id`." Established only
12
+ * when the verifying key came from a trusted external source, never from the
13
+ * receipt's own embedded `public_key`.
14
+ *
15
+ * Verified against the receipt's embedded key alone (offline, no options), a
16
+ * successful check is `integrity-only`: it never claims identity binding. Supply
17
+ * `options.identity` to reach `"pinned"` (the signing key is time-valid in the
18
+ * motebit's own succession chain), and additionally `options.anchor` to reach
19
+ * `"anchored"` (that binding is in the relay's transparency log AND the log root
20
+ * is independently confirmed on-chain). Callers branch on `binding`, not
21
+ * `integrity`, before rendering "from <motebit>".
22
+ *
23
+ * Browser-safe; composes `@motebit/crypto` verifiers + an injectable on-chain
24
+ * lookup — no new crypto here.
25
+ *
26
+ * Doctrine: `docs/doctrine/self-attesting-system.md`, `docs/doctrine/operator-transparency.md`.
27
+ */
28
+ import { type IdentityLogInclusionProof, type MotebitIdentityFile } from "@motebit/crypto";
29
+ import { type IdentityAnchorLookupOptions } from "./identity-anchor.js";
30
+ import { type KeyRevocationLookupOptions } from "./key-revocation.js";
31
+ /**
32
+ * Identity-binding status — a ladder of increasing trust-minimization, per
33
+ * `docs/doctrine/identity-binding-verification.md`. `"unverified"` (signature
34
+ * failed) < `"integrity-only"` (signed, but checked against the receipt's own
35
+ * embedded key — not bound) < `"pinned"` (the signing key is time-valid for an
36
+ * identity file the caller supplied; sovereign chain verified, no operator
37
+ * anchor) < `"anchored"` (the motebit's key is committed in the relay's
38
+ * identity-transparency log AND that log root is independently confirmed on-chain
39
+ * — operator non-equivocation) < `"sovereign"` (the `motebit_id` IS the commitment
40
+ * to the genesis key, verified offline from the identity file alone — no operator,
41
+ * no anchor, no chain; the strongest root).
42
+ *
43
+ * `"revoked"` is off the ladder — a poison verdict. The signature may be valid,
44
+ * but the signing key was revoked on-chain at/before the receipt's timestamp, so
45
+ * the producer claim must NOT be trusted. It overrides every other status.
46
+ */
47
+ export type ReceiptBindingStatus = "revoked" | "sovereign" | "anchored" | "pinned" | "integrity-only" | "unverified";
48
+ export type ReceiptDocumentFailureReason = "malformed_json" | "not_a_receipt" | "missing_public_key" | "signature_invalid" | "delegation_failed" | "unknown";
49
+ /** Honest, recursive view model for a verified (or rejected) receipt document. */
50
+ export interface ReceiptDocumentVerification {
51
+ /**
52
+ * True iff the signature verified (and every delegation verified) — INTEGRITY.
53
+ * A `true` here does NOT mean the key belongs to `motebitId`; read `binding`.
54
+ */
55
+ readonly integrity: boolean;
56
+ /**
57
+ * Identity-binding status (the ladder). `"anchored"` when the binding is in the
58
+ * relay's transparency log AND that root is confirmed on-chain; `"pinned"` when
59
+ * the signing key is time-valid for a caller-supplied identity file;
60
+ * `"integrity-only"` when only the signature is verified against the receipt's
61
+ * own embedded key; `"unverified"` when the signature did not verify. Surfaces
62
+ * MUST NOT render "from <motebit>" below `"pinned"`.
63
+ */
64
+ readonly binding: ReceiptBindingStatus;
65
+ /** The Solana tx that anchored the log root, when `binding === "anchored"`. */
66
+ readonly anchorTxHash?: string;
67
+ /** When `binding === "revoked"`: the on-chain revocation timestamp (ms). */
68
+ readonly revokedAt?: number;
69
+ /** `did:key:z…` derived from the signing key when integrity holds. */
70
+ readonly signerDid?: string;
71
+ /** The producing `motebit_id` as carried in the receipt body — a claim, not proof. */
72
+ readonly motebitId?: string;
73
+ readonly taskId?: string;
74
+ /** Per-delegation results, recursive — mirrors the delegation chain. */
75
+ readonly delegations?: ReceiptDocumentVerification[];
76
+ /** Typed failure reason when `integrity` is false. */
77
+ readonly reason?: ReceiptDocumentFailureReason;
78
+ /** Free-form detail (e.g. underlying error message). */
79
+ readonly detail?: string;
80
+ }
81
+ /**
82
+ * Material for the `anchored` rung: the relay's identity-transparency inclusion
83
+ * proof plus the out-of-band pinned relay Solana address to cross-check it
84
+ * against. Both come from the relay's `/identity/:motebitId` bundle EXCEPT
85
+ * `relayAnchorAddress`, which MUST be pinned independently (not taken from the
86
+ * bundle) — that's the trust root that makes the on-chain check non-circular.
87
+ */
88
+ export interface ReceiptAnchorOptions {
89
+ /** The relay bundle's `anchored.proof` — its `anchoredRoot` is checked on-chain. */
90
+ readonly proof: IdentityLogInclusionProof;
91
+ /** Pinned relay Solana address (out-of-band trust root). */
92
+ readonly relayAnchorAddress: string;
93
+ /** Solana RPC / fetch injection for the on-chain lookup. */
94
+ readonly lookup?: IdentityAnchorLookupOptions;
95
+ }
96
+ export interface VerifyReceiptDocumentOptions {
97
+ /**
98
+ * The producing motebit's identity file (its self-signed succession material).
99
+ * When supplied, and the receipt's signing key is time-valid for it (and the
100
+ * `motebit_id` matches), the result's root upgrades to `binding: "pinned"` —
101
+ * verified against material the caller supplied. The `anchored` / `sovereign`
102
+ * rungs layer operator non-equivocation on top; see
103
+ * `docs/doctrine/identity-binding-verification.md`.
104
+ */
105
+ readonly identity?: MotebitIdentityFile;
106
+ /**
107
+ * Anchor material. Requires `identity` too — `anchored` is `pinned` PLUS an
108
+ * on-chain-confirmed transparency-log inclusion. When the inclusion proof and
109
+ * the on-chain root cross-check both pass, the root upgrades to
110
+ * `binding: "anchored"`; otherwise it degrades honestly to `pinned` /
111
+ * `integrity-only`.
112
+ */
113
+ readonly anchor?: ReceiptAnchorOptions;
114
+ /**
115
+ * On-chain revocation check. The signing key is scanned for a revocation memo
116
+ * at the relay's pinned address (read from the neutral chain, NOT the relay's
117
+ * word — the relay could hide a revocation that protects it). If the key was
118
+ * revoked at/before the receipt's `completed_at`, `binding` is `"revoked"`,
119
+ * overriding every other rung. Requires no `identity` — a revoked key poisons
120
+ * even the integrity-only claim.
121
+ */
122
+ readonly revocation?: {
123
+ readonly relayAnchorAddress: string;
124
+ readonly lookup?: KeyRevocationLookupOptions;
125
+ };
126
+ }
127
+ /**
128
+ * Verify a pasted receipt document (JSON text) entirely offline. Returns a typed
129
+ * view model; never throws on bad input or a crypto failure — only `JSON.parse`
130
+ * and shape errors map to `malformed_json` / `not_a_receipt`. Pass
131
+ * `options.identity` to attempt the `"pinned"` binding rung.
132
+ */
133
+ export declare function verifyReceiptDocument(jsonText: string, options?: VerifyReceiptDocumentOptions): Promise<ReceiptDocumentVerification>;
134
+ //# sourceMappingURL=receipt-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-document.d.ts","sourceRoot":"","sources":["../src/receipt-document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAIL,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAA2B,KAAK,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAE3F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,MAAM,4BAA4B,GACpC,gBAAgB,GAChB,eAAe,GACf,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,SAAS,CAAC;AAEd,kFAAkF;AAClF,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,sFAAsF;IACtF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,WAAW,CAAC,EAAE,2BAA2B,EAAE,CAAC;IACrD,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,4BAA4B,CAAC;IAC/C,wDAAwD;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AA8DD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,4DAA4D;IAC5D,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,CAAC,EAAE,2BAA2B,CAAC;CAC/C;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,0BAA0B,CAAC;KAC9C,CAAC;CACH;AAoED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,2BAA2B,CAAC,CAiDtC"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Verify a pasted/standalone `ExecutionReceipt` document and project it into an
3
+ * honest, display-ready view model — the brain behind a public receipt verifier
4
+ * (e.g. receipt.computer): paste a receipt, learn what it actually proves.
5
+ *
6
+ * The model's whole point is to keep two facts separate, the way the rest of the
7
+ * stack now does (crypto `keySource`, render-engine `bindingStatusFor`):
8
+ *
9
+ * - INTEGRITY — "the bytes were signed by *some* key and nothing was tampered."
10
+ * Always checkable offline from the receipt alone.
11
+ * - BINDING — "that key belongs to the claimed `motebit_id`." Established only
12
+ * when the verifying key came from a trusted external source, never from the
13
+ * receipt's own embedded `public_key`.
14
+ *
15
+ * Verified against the receipt's embedded key alone (offline, no options), a
16
+ * successful check is `integrity-only`: it never claims identity binding. Supply
17
+ * `options.identity` to reach `"pinned"` (the signing key is time-valid in the
18
+ * motebit's own succession chain), and additionally `options.anchor` to reach
19
+ * `"anchored"` (that binding is in the relay's transparency log AND the log root
20
+ * is independently confirmed on-chain). Callers branch on `binding`, not
21
+ * `integrity`, before rendering "from <motebit>".
22
+ *
23
+ * Browser-safe; composes `@motebit/crypto` verifiers + an injectable on-chain
24
+ * lookup — no new crypto here.
25
+ *
26
+ * Doctrine: `docs/doctrine/self-attesting-system.md`, `docs/doctrine/operator-transparency.md`.
27
+ */
28
+ import { verifyReceipt, verifyKeyBindingAtTime, verifyIdentityBindingAnchored, } from "@motebit/crypto";
29
+ import { lookupIdentityLogAnchor } from "./identity-anchor.js";
30
+ import { lookupKeyRevocation } from "./key-revocation.js";
31
+ /**
32
+ * Minimal structural guard for user-pasted input. We verify at the boundary
33
+ * (untrusted text) before handing to crypto — a non-receipt object must surface
34
+ * as a typed `not_a_receipt`, never an opaque downstream throw.
35
+ */
36
+ function isExecutionReceiptShape(value) {
37
+ if (typeof value !== "object" || value === null)
38
+ return false;
39
+ const r = value;
40
+ return (typeof r["motebit_id"] === "string" &&
41
+ typeof r["task_id"] === "string" &&
42
+ typeof r["signature"] === "string" &&
43
+ typeof r["suite"] === "string");
44
+ }
45
+ function toView(result) {
46
+ const errs = result.errors ?? [];
47
+ const base = {
48
+ integrity: result.valid,
49
+ // `verifyReceipt` checks the signature against the receipt's own embedded
50
+ // key, so on its own a valid check is integrity-only. `verifyReceiptDocument`
51
+ // upgrades the root to `"pinned"` when a matching identity file is supplied.
52
+ binding: result.valid ? "integrity-only" : "unverified",
53
+ };
54
+ if (result.signer !== undefined)
55
+ base.signerDid = result.signer;
56
+ if (result.receipt) {
57
+ base.motebitId = String(result.receipt.motebit_id);
58
+ base.taskId = result.receipt.task_id;
59
+ }
60
+ if (result.delegations && result.delegations.length > 0) {
61
+ base.delegations = result.delegations.map(toView);
62
+ }
63
+ if (!result.valid) {
64
+ if (errs.some((e) => e.message.includes("No embedded public_key"))) {
65
+ base.reason = "missing_public_key";
66
+ }
67
+ else if (errs.some((e) => e.path === "delegation_receipts")) {
68
+ base.reason = "delegation_failed";
69
+ }
70
+ else if (errs.length > 0) {
71
+ base.reason = "signature_invalid";
72
+ }
73
+ else {
74
+ base.reason = "unknown";
75
+ }
76
+ const detail = errs[0]?.message;
77
+ if (detail !== undefined)
78
+ base.detail = detail;
79
+ }
80
+ return base;
81
+ }
82
+ /**
83
+ * Promote the root to `"pinned"` iff the supplied identity file is for this
84
+ * receipt's motebit and its succession chain makes the signing key valid at the
85
+ * receipt's `completed_at`. Returns `null` (no promotion) otherwise. The chain is
86
+ * verified inside `verifyKeyBindingAtTime`; this is the sovereign-root half of
87
+ * binding (no operator anchor).
88
+ */
89
+ async function pinnedBinding(receipt, identity) {
90
+ if (typeof receipt.public_key !== "string")
91
+ return null;
92
+ if (String(identity.motebit_id) !== String(receipt.motebit_id))
93
+ return null;
94
+ const r = await verifyKeyBindingAtTime(identity, receipt.public_key, receipt.completed_at);
95
+ return r.bound ? "pinned" : null;
96
+ }
97
+ /**
98
+ * Promote to `"sovereign"` iff the signing key binds AND the identity's
99
+ * `motebit_id` is the sovereign commitment to its genesis key. This is the
100
+ * strongest rung and the only fully-offline one — `verifyKeyBindingAtTime`
101
+ * computes both the key's window and the id↔genesis commitment from the identity
102
+ * file alone, so no anchor, no relay, no chain is consulted. Returns `null`
103
+ * (no promotion) when the motebit wasn't minted sovereignly.
104
+ */
105
+ async function sovereignBinding(receipt, identity) {
106
+ if (typeof receipt.public_key !== "string")
107
+ return null;
108
+ if (String(identity.motebit_id) !== String(receipt.motebit_id))
109
+ return null;
110
+ const r = await verifyKeyBindingAtTime(identity, receipt.public_key, receipt.completed_at);
111
+ return r.bound === true && r.sovereign === true ? "sovereign" : null;
112
+ }
113
+ /**
114
+ * Promote to `"anchored"` iff (a) the signing key is sovereign-bound to the
115
+ * supplied identity at `completed_at` AND included under `anchor.proof`'s root
116
+ * (`verifyIdentityBindingAnchored`), AND (b) that root is independently confirmed
117
+ * on-chain at the pinned relay address (`lookupIdentityLogAnchor`). The second
118
+ * check is what makes it `anchored` rather than `pinned` — without it a relay
119
+ * could assert any root. Returns the anchoring `txHash` for provenance, or `null`
120
+ * (no promotion) on any failure.
121
+ */
122
+ async function anchoredBinding(receipt, identity, anchor) {
123
+ if (typeof receipt.public_key !== "string")
124
+ return null;
125
+ if (String(identity.motebit_id) !== String(receipt.motebit_id))
126
+ return null;
127
+ const bound = await verifyIdentityBindingAnchored(identity, receipt.public_key, receipt.completed_at, anchor.proof);
128
+ if (!bound.bound)
129
+ return null;
130
+ const onchain = await lookupIdentityLogAnchor(anchor.relayAnchorAddress, anchor.proof.anchoredRoot, anchor.lookup);
131
+ return onchain.ok ? { txHash: onchain.txHash } : null;
132
+ }
133
+ /**
134
+ * Verify a pasted receipt document (JSON text) entirely offline. Returns a typed
135
+ * view model; never throws on bad input or a crypto failure — only `JSON.parse`
136
+ * and shape errors map to `malformed_json` / `not_a_receipt`. Pass
137
+ * `options.identity` to attempt the `"pinned"` binding rung.
138
+ */
139
+ export async function verifyReceiptDocument(jsonText, options) {
140
+ let parsed;
141
+ try {
142
+ parsed = JSON.parse(jsonText);
143
+ }
144
+ catch (err) {
145
+ return {
146
+ integrity: false,
147
+ binding: "unverified",
148
+ reason: "malformed_json",
149
+ detail: err instanceof Error ? err.message : String(err),
150
+ };
151
+ }
152
+ if (!isExecutionReceiptShape(parsed)) {
153
+ return {
154
+ integrity: false,
155
+ binding: "unverified",
156
+ reason: "not_a_receipt",
157
+ detail: "input is not an ExecutionReceipt (missing motebit_id / task_id / signature / suite)",
158
+ };
159
+ }
160
+ const view = toView(await verifyReceipt(parsed));
161
+ if (view.integrity) {
162
+ // Revocation is a poison verdict — check it first, independent of `identity`.
163
+ // A key revoked on-chain at/before completed_at must not bind, no matter what
164
+ // the succession chain says.
165
+ if (options?.revocation && typeof parsed.public_key === "string") {
166
+ const rev = await lookupKeyRevocation(options.revocation.relayAnchorAddress, parsed.public_key, options.revocation.lookup);
167
+ if (rev.status === "revoked" && rev.revokedAt <= parsed.completed_at) {
168
+ return { ...view, binding: "revoked", revokedAt: rev.revokedAt };
169
+ }
170
+ }
171
+ if (options?.identity) {
172
+ // Sovereign is the strongest root AND fully offline — check it first; a
173
+ // sovereign motebit needs no operator anchor at all.
174
+ const sovereign = await sovereignBinding(parsed, options.identity);
175
+ if (sovereign)
176
+ return { ...view, binding: sovereign };
177
+ if (options.anchor) {
178
+ const anchored = await anchoredBinding(parsed, options.identity, options.anchor);
179
+ if (anchored)
180
+ return { ...view, binding: "anchored", anchorTxHash: anchored.txHash };
181
+ }
182
+ const pinned = await pinnedBinding(parsed, options.identity);
183
+ if (pinned)
184
+ return { ...view, binding: pinned };
185
+ }
186
+ }
187
+ return view;
188
+ }
189
+ //# sourceMappingURL=receipt-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-document.js","sourceRoot":"","sources":["../src/receipt-document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,6BAA6B,GAG9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,uBAAuB,EAAoC,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAmC,MAAM,qBAAqB,CAAC;AAmE3F;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,KAAc;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,QAAQ;QACnC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,QAAQ;QAChC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,QAAQ;QAClC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAC/B,CAAC;AACJ,CAAC;AAID,SAAS,MAAM,CAAC,MAA2B;IACzC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACjC,MAAM,IAAI,GASN;QACF,SAAS,EAAE,MAAM,CAAC,KAAK;QACvB,0EAA0E;QAC1E,8EAA8E;QAC9E,6EAA6E;QAC7E,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY;KACxD,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAChE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;IACvC,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC;QACrC,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC,EAAE,CAAC;YAC9D,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC;QACpC,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QAC1B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;QAChC,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAkDD;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,OAAyB,EACzB,QAA6B;IAE7B,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,MAAM,CAAC,GAAG,MAAM,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3F,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,gBAAgB,CAC7B,OAAyB,EACzB,QAA6B;IAE7B,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,MAAM,CAAC,GAAG,MAAM,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3F,OAAO,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,eAAe,CAC5B,OAAyB,EACzB,QAA6B,EAC7B,MAA4B;IAE5B,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,MAAM,KAAK,GAAG,MAAM,6BAA6B,CAC/C,QAAQ,EACR,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,YAAY,EACpB,MAAM,CAAC,KAAK,CACb,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAC3C,MAAM,CAAC,kBAAkB,EACzB,MAAM,CAAC,KAAK,CAAC,YAAY,EACzB,MAAM,CAAC,MAAM,CACd,CAAC;IACF,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB,EAChB,OAAsC;IAEtC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,YAAY;YACrB,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,YAAY;YACrB,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,qFAAqF;SAC9F,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,8EAA8E;QAC9E,8EAA8E;QAC9E,6BAA6B;QAC7B,IAAI,OAAO,EAAE,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACjE,MAAM,GAAG,GAAG,MAAM,mBAAmB,CACnC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EACrC,MAAM,CAAC,UAAU,EACjB,OAAO,CAAC,UAAU,CAAC,MAAM,CAC1B,CAAC;YACF,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBACrE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;QACD,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;YACtB,wEAAwE;YACxE,qDAAqD;YACrD,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACnE,IAAI,SAAS;gBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;YACtD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBACjF,IAAI,QAAQ;oBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvF,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,MAAM;gBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motebit/state-export-client",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Browser-safe client for verified motebit state-export reads. Wraps fetch with X-Motebit-Content-Manifest verification + Trust-On-First-Use bootstrap from /.well-known/motebit-transparency.json. Apache-2.0; consumes @motebit/crypto + @motebit/protocol only.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,8 +35,8 @@
35
35
  "operator-transparency"
36
36
  ],
37
37
  "dependencies": {
38
- "@motebit/crypto": "1.3.0",
39
- "@motebit/protocol": "1.3.0"
38
+ "@motebit/crypto": "2.0.0",
39
+ "@motebit/protocol": "2.0.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22.0.0",