zklicensing 0.1.0-beta.2 → 0.1.0-beta.4

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.
Files changed (173) hide show
  1. package/README.md +335 -97
  2. package/build/appsLookup.d.ts +14 -0
  3. package/build/appsLookup.d.ts.map +1 -0
  4. package/build/appsLookup.js +12 -0
  5. package/build/appsLookup.js.map +1 -0
  6. package/build/archiveBootstrap.d.ts +15 -1
  7. package/build/archiveBootstrap.d.ts.map +1 -0
  8. package/build/archiveBootstrap.js +62 -9
  9. package/build/archiveBootstrap.js.map +1 -0
  10. package/build/bindClient.d.ts +51 -0
  11. package/build/bindClient.d.ts.map +1 -0
  12. package/build/bindClient.js +115 -0
  13. package/build/bindClient.js.map +1 -0
  14. package/build/buyClient.d.ts +10 -3
  15. package/build/buyClient.d.ts.map +1 -0
  16. package/build/buyClient.js +33 -15
  17. package/build/buyClient.js.map +1 -0
  18. package/build/contractInterface.d.ts +11 -5
  19. package/build/contractInterface.d.ts.map +1 -0
  20. package/build/contractInterface.js +82 -17
  21. package/build/contractInterface.js.map +1 -0
  22. package/build/countryStats.d.ts +6 -1
  23. package/build/countryStats.d.ts.map +1 -0
  24. package/build/countryStats.js +33 -9
  25. package/build/countryStats.js.map +1 -0
  26. package/build/deployClient.d.ts.map +1 -0
  27. package/build/deployClient.js +1 -1
  28. package/build/deployClient.js.map +1 -0
  29. package/build/deviceIdentity.d.ts +68 -0
  30. package/build/deviceIdentity.d.ts.map +1 -0
  31. package/build/deviceIdentity.js +209 -0
  32. package/build/deviceIdentity.js.map +1 -0
  33. package/build/freezeClient.d.ts.map +1 -0
  34. package/build/freezeClient.js +1 -1
  35. package/build/freezeClient.js.map +1 -0
  36. package/build/generationClient.d.ts +1 -0
  37. package/build/generationClient.d.ts.map +1 -0
  38. package/build/generationClient.js +2 -2
  39. package/build/generationClient.js.map +1 -0
  40. package/build/index.d.ts +27 -37
  41. package/build/index.d.ts.map +1 -0
  42. package/build/index.js +85 -116
  43. package/build/index.js.map +1 -0
  44. package/build/licenseLeaf.d.ts +76 -0
  45. package/build/licenseLeaf.d.ts.map +1 -0
  46. package/build/licenseLeaf.js +189 -0
  47. package/build/licenseLeaf.js.map +1 -0
  48. package/build/licenseRecord.d.ts +20 -1
  49. package/build/licenseRecord.d.ts.map +1 -0
  50. package/build/licenseRecord.js +1 -1
  51. package/build/licenseRecord.js.map +1 -0
  52. package/build/licenseStore.d.ts +17 -2
  53. package/build/licenseStore.d.ts.map +1 -0
  54. package/build/licenseStore.js +167 -7
  55. package/build/licenseStore.js.map +1 -0
  56. package/build/manifestVerify.d.ts.map +1 -0
  57. package/build/manifestVerify.js +8 -3
  58. package/build/manifestVerify.js.map +1 -0
  59. package/build/migrateClient.d.ts +6 -21
  60. package/build/migrateClient.d.ts.map +1 -0
  61. package/build/migrateClient.js +30 -17
  62. package/build/migrateClient.js.map +1 -0
  63. package/build/onChainRoot.d.ts +67 -0
  64. package/build/onChainRoot.d.ts.map +1 -0
  65. package/build/onChainRoot.js +87 -0
  66. package/build/onChainRoot.js.map +1 -0
  67. package/build/ownershipLicenseHash.d.ts +25 -0
  68. package/build/ownershipLicenseHash.d.ts.map +1 -0
  69. package/build/ownershipLicenseHash.js +29 -0
  70. package/build/ownershipLicenseHash.js.map +1 -0
  71. package/build/ownershipSignature.d.ts +122 -0
  72. package/build/ownershipSignature.d.ts.map +1 -0
  73. package/build/ownershipSignature.js +244 -0
  74. package/build/ownershipSignature.js.map +1 -0
  75. package/build/proveErrors.d.ts +35 -0
  76. package/build/proveErrors.d.ts.map +1 -0
  77. package/build/proveErrors.js +49 -0
  78. package/build/proveErrors.js.map +1 -0
  79. package/build/refundClient.d.ts +2 -11
  80. package/build/refundClient.d.ts.map +1 -0
  81. package/build/refundClient.js +35 -17
  82. package/build/refundClient.js.map +1 -0
  83. package/build/renewClient.d.ts +4 -1
  84. package/build/renewClient.d.ts.map +1 -0
  85. package/build/renewClient.js +11 -4
  86. package/build/renewClient.js.map +1 -0
  87. package/build/seatName.d.ts +8 -0
  88. package/build/seatName.d.ts.map +1 -0
  89. package/build/seatName.js +136 -0
  90. package/build/seatName.js.map +1 -0
  91. package/build/statsClient.d.ts +47 -4
  92. package/build/statsClient.d.ts.map +1 -0
  93. package/build/statsClient.js +44 -5
  94. package/build/statsClient.js.map +1 -0
  95. package/build/trustAnchorVerify.d.ts +48 -0
  96. package/build/trustAnchorVerify.d.ts.map +1 -0
  97. package/build/trustAnchorVerify.js +431 -0
  98. package/build/trustAnchorVerify.js.map +1 -0
  99. package/build/trustAnchorVerifyCli.d.ts +35 -0
  100. package/build/trustAnchorVerifyCli.d.ts.map +1 -0
  101. package/build/trustAnchorVerifyCli.js +177 -0
  102. package/build/trustAnchorVerifyCli.js.map +1 -0
  103. package/build/txBroadcastClient.d.ts +26 -0
  104. package/build/txBroadcastClient.d.ts.map +1 -0
  105. package/build/txBroadcastClient.js +20 -0
  106. package/build/txBroadcastClient.js.map +1 -0
  107. package/build/unbindClient.d.ts +56 -0
  108. package/build/unbindClient.d.ts.map +1 -0
  109. package/build/unbindClient.js +113 -0
  110. package/build/unbindClient.js.map +1 -0
  111. package/build/vendorAccountClient.d.ts +56 -0
  112. package/build/vendorAccountClient.d.ts.map +1 -0
  113. package/build/vendorAccountClient.js +47 -0
  114. package/build/vendorAccountClient.js.map +1 -0
  115. package/build/verifyCore.d.ts +1 -1
  116. package/build/verifyCore.d.ts.map +1 -0
  117. package/build/verifyCore.js +11 -4
  118. package/build/verifyCore.js.map +1 -0
  119. package/build/verifyOffline.d.ts +85 -0
  120. package/build/verifyOffline.d.ts.map +1 -0
  121. package/build/verifyOffline.js +139 -0
  122. package/build/verifyOffline.js.map +1 -0
  123. package/build/verifyService.d.ts.map +1 -0
  124. package/build/verifyService.js +582 -455
  125. package/build/verifyService.js.map +1 -0
  126. package/build/verifyWithAncestors.d.ts +18 -0
  127. package/build/verifyWithAncestors.d.ts.map +1 -0
  128. package/build/verifyWithAncestors.js +119 -0
  129. package/build/verifyWithAncestors.js.map +1 -0
  130. package/build/zipToState.d.ts +2 -0
  131. package/build/zipToState.d.ts.map +1 -0
  132. package/build/zipToState.js +94 -0
  133. package/build/zipToState.js.map +1 -0
  134. package/package.json +57 -13
  135. package/src/appsLookup.ts +48 -0
  136. package/src/archiveBootstrap.ts +342 -0
  137. package/src/bindClient.ts +175 -0
  138. package/src/buyClient.ts +304 -0
  139. package/src/contractInterface.d.ts +61 -0
  140. package/src/contractInterface.ts +313 -0
  141. package/src/countryStats.ts +171 -0
  142. package/src/deployClient.ts +388 -0
  143. package/src/deviceIdentity.ts +249 -0
  144. package/src/freezeClient.ts +117 -0
  145. package/src/generationClient.ts +165 -0
  146. package/src/index.ts +329 -0
  147. package/src/licenseLeaf.ts +221 -0
  148. package/src/licenseRecord.ts +108 -0
  149. package/src/licenseStore.ts +538 -0
  150. package/src/manifestVerify.ts +111 -0
  151. package/src/migrateClient.ts +84 -0
  152. package/src/onChainRoot.ts +107 -0
  153. package/src/ownershipLicenseHash.ts +31 -0
  154. package/src/ownershipSignature.ts +354 -0
  155. package/src/proveErrors.ts +70 -0
  156. package/src/refundClient.ts +158 -0
  157. package/src/renewClient.ts +214 -0
  158. package/src/seatName.ts +165 -0
  159. package/src/statsClient.ts +235 -0
  160. package/src/trustAnchorVerify.ts +548 -0
  161. package/src/trustAnchorVerifyCli.ts +179 -0
  162. package/src/txBroadcastClient.ts +48 -0
  163. package/src/unbindClient.ts +149 -0
  164. package/src/vendorAccountClient.ts +110 -0
  165. package/src/verifyCore.ts +92 -0
  166. package/src/verifyOffline.ts +212 -0
  167. package/src/verifyService.ts +969 -0
  168. package/src/verifyWithAncestors.ts +153 -0
  169. package/src/zipToState.ts +94 -0
  170. package/build/licenseProof.d.ts +0 -26
  171. package/build/licenseProof.js +0 -41
  172. package/build/ownership.d.ts +0 -34
  173. package/build/ownership.js +0 -147
@@ -0,0 +1,48 @@
1
+ export type Finding = {
2
+ /** Machine-readable check identifier, stable across releases. */
3
+ name: string;
4
+ /** True iff the check passed. */
5
+ ok: boolean;
6
+ /** Human-readable one-line summary or reason. */
7
+ detail: string;
8
+ };
9
+ export type TrustAnchorReport = {
10
+ /** True iff every finding is ok. */
11
+ ok: boolean;
12
+ origin: string;
13
+ /** Address that was checked. Echoed from opts.address. */
14
+ address: string;
15
+ /** appId as declared in the signed manifest payload. Undefined if the fetch/signature failed. */
16
+ appId?: string;
17
+ /** Generation index the address maps to in the signed manifest (1-based). */
18
+ generation?: number;
19
+ findings: Finding[];
20
+ };
21
+ export interface VerifyTrustAnchorOpts {
22
+ /** Vendor origin, e.g. `https://store.example.com`. HTTPS required. */
23
+ origin: string;
24
+ /** zkApp address (base58 PublicKey) — the manifest lives at `/.well-known/zklicensing/<address>.json`. */
25
+ address: string;
26
+ /** Platform manifest Ed25519 public keys (base64). Comma-list from `VITE_MANIFEST_PUBKEYS`. */
27
+ pinnedPublicKeysBase64: readonly string[];
28
+ /** Mina GraphQL endpoint for on-chain reads. Ignored when `skipChainChecks` is true. */
29
+ minaGraphqlUrl?: string;
30
+ /** Optional Mina networkId — 'mainnet' or 'testnet'. Defaults to 'mainnet'. */
31
+ minaNetworkId?: 'mainnet' | 'testnet' | 'devnet';
32
+ /** Fetch timeout in ms for the manifest fetch. Default 15000. */
33
+ fetchTimeoutMs?: number;
34
+ /** When true, skips all `chain_*` checks. Useful for manifest-only audits. */
35
+ skipChainChecks?: boolean;
36
+ /**
37
+ * When true, runs an extra `manifest_matches_backend` finding: fetch the
38
+ * same signed payload from `https://zklicensing.com/apps/by-address/{address}`,
39
+ * verify it against the same pinned keys, then byte-compare canonicalized
40
+ * payloads (minus `signature`, `publicKey`, `issuedAt`, `app`). Catches a
41
+ * vendor serving a stale/rolled-back manifest even when its own signature
42
+ * is still valid. Not on by default — adds a second network fetch and
43
+ * couples the verifier to zklicensing.com being reachable.
44
+ */
45
+ crossCheck?: boolean;
46
+ }
47
+ export declare function verifyTrustAnchor(opts: VerifyTrustAnchorOpts): Promise<TrustAnchorReport>;
48
+ //# sourceMappingURL=trustAnchorVerify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trustAnchorVerify.d.ts","sourceRoot":"","sources":["../src/trustAnchorVerify.ts"],"names":[],"mappings":"AAyDA,MAAM,MAAM,OAAO,GAAG;IACpB,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,0GAA0G;IAC1G,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8PD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6L/F"}
@@ -0,0 +1,431 @@
1
+ // Copyright (c) 2025-2026 zkLicensing project developers
2
+ // SPDX-License-Identifier: BUSL-1.1
3
+ /**
4
+ * trustAnchorVerify.ts
5
+ *
6
+ * End-to-end trust-anchor verification for a single zkLicensing app.
7
+ *
8
+ * Given a vendor origin + a zkApp address + one or more pinned platform
9
+ * manifest public keys, this module performs the full "does this vendor
10
+ * page point at a real zkLicensing deployment for this vendor?" pipeline
11
+ * that the trust-anchor page walks a human buyer through — mechanically,
12
+ * with structured findings suitable for CI, monitoring, or a
13
+ * wallet/extension consumer.
14
+ *
15
+ * The verifier is address-keyed: buyers see zkApp addresses in their
16
+ * wallet popup, not opaque platform appIds, so the primary lookup is by
17
+ * address. The signed manifest served at
18
+ * `<origin>/.well-known/zklicensing/<zkAppAddress>.json` carries the
19
+ * appId inside its signed payload, so callers never need to know the
20
+ * appId out-of-band.
21
+ *
22
+ * Pipeline (each step yields a discrete Finding — no boolean collapse):
23
+ *
24
+ * 1. manifest_fetch — GET https://<origin>/.well-known/zklicensing/<address>.json
25
+ * 2. manifest_signature — Ed25519 verify against caller-provided pinned keys
26
+ * 3. manifest_address_in_generations — opts.address appears in the signed generations[]
27
+ * 3b. manifest_matches_backend — (opt-in, opts.crossCheck) vendor payload equals
28
+ * zklicensing.com/apps/by-address/<address> after
29
+ * independent signature-verify against same pins
30
+ * 4. chain_account_exists — fetchAccount succeeds at the address
31
+ * 5. chain_zkapp_uri_match — on-chain zkappUri equals opts.origin
32
+ * 6. chain_vk_hash_pinned — on-chain verification-key hash equals CANONICAL_VK_HASHES[generation]
33
+ * 7. chain_set_zkapp_uri_impossible — permissions.setZkappUri === Permissions.impossible()
34
+ * 8. chain_set_permissions_impossible — permissions.setPermissions === Permissions.impossible() (meta-freeze)
35
+ * 9. chain_set_verification_key_locked — permissions.setVerificationKey.auth === Permissions.impossible()
36
+ * 10. chain_send_proof_only — permissions.send === Permissions.proof()
37
+ * 11. chain_edit_state_proof_only — permissions.editState === Permissions.proof()
38
+ *
39
+ * Steps 5 + 7 close the URI-binding loop: (5) proves the contract claims
40
+ * this origin, (7) proves nobody can rewrite that claim. Steps 8–11 verify
41
+ * the rest of LicensingApp.init()'s permission matrix — catching the case
42
+ * where a deployer used the correct VK but skipped/altered init(), leaving
43
+ * default `signature()` permissions that would still let the deploy key
44
+ * drain escrow, rewrite state, or swap the circuit.
45
+ *
46
+ * o1js is a peer dependency — this file imports it dynamically so callers
47
+ * that only want the manifest checks (no chain reads) can construct one
48
+ * with `skipChainChecks: true` and avoid the o1js install.
49
+ *
50
+ * The pinned pubkey list is caller-supplied — the SDK ships NO baked-in
51
+ * pin. Source it from https://zklicensing.com/trustanchor.html (published
52
+ * next to each generation's VK hash). See the SDK README for details.
53
+ */
54
+ import { verifyManifestSignature, canonicalize } from './manifestVerify.js';
55
+ // Production keeper is mounted under /api/keeper on zklicensing.com — the
56
+ // bare /apps/... paths return 404 (they're not the app route, they're an
57
+ // unrelated marketing route). This is the concrete URL prefix, not just an
58
+ // origin.
59
+ const BACKEND_URL_PREFIX = 'https://zklicensing.com/api/keeper';
60
+ const DEFAULT_FETCH_TIMEOUT_MS = 15000;
61
+ function normalizeOrigin(origin) {
62
+ return origin.replace(/\/+$/, '');
63
+ }
64
+ // Strip trailing slash / path from a URL so we can compare against zkappUri,
65
+ // which vendors typically set to their bare origin.
66
+ function urlOrigin(url) {
67
+ try {
68
+ const u = new URL(url);
69
+ return `${u.protocol}//${u.host}`;
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ async function fetchManifest(origin, address, timeoutMs) {
76
+ const originOk = origin.startsWith('https://');
77
+ if (!originOk) {
78
+ return { name: 'manifest_fetch', ok: false, detail: 'origin must be https://' };
79
+ }
80
+ let manifestUrl;
81
+ try {
82
+ manifestUrl = new URL(`/.well-known/zklicensing/${encodeURIComponent(address)}.json`, origin).href;
83
+ }
84
+ catch {
85
+ return { name: 'manifest_fetch', ok: false, detail: 'origin is not a valid URL' };
86
+ }
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
89
+ try {
90
+ const resp = await fetch(manifestUrl, { signal: controller.signal, redirect: 'follow' });
91
+ if (!resp.ok) {
92
+ return { name: 'manifest_fetch', ok: false, detail: `HTTP ${resp.status} from ${manifestUrl}` };
93
+ }
94
+ const text = await resp.text();
95
+ let parsed;
96
+ try {
97
+ parsed = JSON.parse(text);
98
+ }
99
+ catch {
100
+ return { name: 'manifest_fetch', ok: false, detail: 'response is not valid JSON' };
101
+ }
102
+ return { name: 'manifest_fetch', ok: true, detail: `fetched ${manifestUrl}`, body: parsed };
103
+ }
104
+ catch (err) {
105
+ return { name: 'manifest_fetch', ok: false, detail: `fetch failed: ${err?.message ?? String(err)}` };
106
+ }
107
+ finally {
108
+ clearTimeout(timer);
109
+ }
110
+ }
111
+ // Split a raw manifest JSON into { signature, payload }. The keeper writes the
112
+ // payload fields at the top level plus { signature, publicKey } — we ignore
113
+ // publicKey (never trust the payload's self-declared key; only the
114
+ // caller-pinned list is authoritative). The same signed bytes are served at
115
+ // every /.well-known/zklicensing/<address>.json — one file per generation
116
+ // address, all carrying the same appId in the payload.
117
+ function splitManifest(raw) {
118
+ if (!raw || typeof raw !== 'object')
119
+ return { signature: null, payload: null };
120
+ const r = raw;
121
+ const signature = typeof r.signature === 'string' ? r.signature : null;
122
+ const { signature: _s, publicKey: _p, ...rest } = r;
123
+ const payload = rest;
124
+ if (typeof payload.appId !== 'string' ||
125
+ typeof payload.current !== 'number' ||
126
+ !Array.isArray(payload.generations) ||
127
+ typeof payload.issuedAt !== 'string') {
128
+ return { signature, payload: null };
129
+ }
130
+ return { signature, payload };
131
+ }
132
+ // Optional cross-check against the zkLicensing backend's own copy of the
133
+ // signed generation list. Fetches `https://zklicensing.com/apps/by-address/
134
+ // {address}`, verifies its signature against the same caller-pinned keys (so
135
+ // a compromised backend URL cannot lie), strips signature/publicKey/issuedAt/
136
+ // app, and byte-compares canonicalized payloads against the vendor's
137
+ // `.well-known` copy. `issuedAt` is stripped because the backend re-stamps on
138
+ // every call; `app` is stripped because it is an unsigned envelope field the
139
+ // by-address endpoint tacks on.
140
+ async function checkBackendMatch(args) {
141
+ const name = 'manifest_matches_backend';
142
+ const url = `${BACKEND_URL_PREFIX}/apps/by-address/${encodeURIComponent(args.address)}`;
143
+ const controller = new AbortController();
144
+ const timer = setTimeout(() => controller.abort(), args.timeoutMs);
145
+ let body;
146
+ try {
147
+ const resp = await fetch(url, { signal: controller.signal, redirect: 'follow' });
148
+ if (!resp.ok)
149
+ return { name, ok: false, detail: `backend HTTP ${resp.status} from ${url}` };
150
+ body = await resp.json();
151
+ }
152
+ catch (err) {
153
+ return { name, ok: false, detail: `backend fetch failed: ${err?.message ?? String(err)}` };
154
+ }
155
+ finally {
156
+ clearTimeout(timer);
157
+ }
158
+ if (!body || typeof body !== 'object') {
159
+ return { name, ok: false, detail: 'backend response is not a JSON object' };
160
+ }
161
+ const { signature, publicKey: _pub, app: _app, ...backendPayload } = body;
162
+ if (typeof signature !== 'string') {
163
+ return { name, ok: false, detail: 'backend response missing signature' };
164
+ }
165
+ const kSigOk = await verifyManifestSignature(backendPayload, signature, args.pinnedPublicKeysBase64);
166
+ if (!kSigOk) {
167
+ return { name, ok: false, detail: 'backend response signature does not verify against pinned keys' };
168
+ }
169
+ const { issuedAt: _kIA, ...kRest } = backendPayload;
170
+ const { issuedAt: _vIA, ...vRest } = args.vendorPayload;
171
+ if (canonicalize(kRest) !== canonicalize(vRest)) {
172
+ return { name, ok: false, detail: 'vendor manifest content diverges from backend record (stale or drifted)' };
173
+ }
174
+ return { name, ok: true, detail: `vendor payload matches backend /apps/by-address/${args.address}` };
175
+ }
176
+ // Converts an o1js-decoded Permission (three booleans) back to its canonical
177
+ // enum string. Mirrors the switch inside o1js's own AuthRequired.toJSON — kept
178
+ // inline because o1js doesn't publicly export it.
179
+ function permToString(p) {
180
+ const b = (v) => (typeof v?.toBoolean === 'function' ? v.toBoolean() : Boolean(v)) ? 1 : 0;
181
+ const key = `${b(p?.constant)}${b(p?.signatureNecessary)}${b(p?.signatureSufficient)}`;
182
+ switch (key) {
183
+ case '110': return 'Impossible';
184
+ case '101': return 'None';
185
+ case '000': return 'Proof';
186
+ case '011': return 'Signature';
187
+ case '001': return 'Either';
188
+ default: return undefined;
189
+ }
190
+ }
191
+ // Reads the on-chain facts needed to close the trust loop for a single
192
+ // zkApp address. o1js is imported dynamically so this file can be pulled in
193
+ // by callers that don't need chain reads (e.g. an offline manifest audit).
194
+ async function readChainState(address, minaGraphqlUrl, minaNetworkId) {
195
+ let o1js;
196
+ try {
197
+ o1js = await import('o1js');
198
+ }
199
+ catch (err) {
200
+ return {
201
+ accountFound: false,
202
+ fetchError: `o1js not installed — chain checks require o1js as a peer dep (${err?.message ?? err})`,
203
+ };
204
+ }
205
+ try {
206
+ // setActiveInstance mutates o1js global state. This is acceptable for a
207
+ // one-shot CLI; long-lived hosts should confine the call to their own
208
+ // network singleton and not use this helper.
209
+ const network = o1js.Mina.Network({
210
+ networkId: minaNetworkId === 'mainnet' ? 'mainnet' : 'testnet',
211
+ mina: minaGraphqlUrl,
212
+ });
213
+ o1js.Mina.setActiveInstance(network);
214
+ const publicKey = o1js.PublicKey.fromBase58(address);
215
+ const { account, error } = await o1js.fetchAccount({ publicKey });
216
+ if (!account) {
217
+ const detail = error
218
+ ? `${error.statusCode ?? ''} ${error.statusText ?? ''} ${error.errors ? JSON.stringify(error.errors) : ''}`.trim() || JSON.stringify(error)
219
+ : 'no account and no error returned';
220
+ return { accountFound: false, fetchError: `fetchAccount(${address}) via ${minaGraphqlUrl}: ${detail}` };
221
+ }
222
+ const zkappUri = account.zkapp?.zkappUri;
223
+ const vkHash = account.zkapp?.verificationKey?.hash?.toString?.();
224
+ const perms = account.permissions;
225
+ const setVkAuth = permToString(perms?.setVerificationKey?.auth);
226
+ const rawTxnVersion = perms?.setVerificationKey?.txnVersion;
227
+ const setVkTxnVersion = rawTxnVersion?.toString ? Number(rawTxnVersion.toString()) : undefined;
228
+ return {
229
+ accountFound: true,
230
+ zkappUri,
231
+ vkHash,
232
+ setZkappUriIsImpossible: permToString(perms?.setZkappUri) === 'Impossible',
233
+ setPermissionsIsImpossible: permToString(perms?.setPermissions) === 'Impossible',
234
+ setVerificationKeyAuth: setVkAuth,
235
+ setVerificationKeyTxnVersion: Number.isFinite(setVkTxnVersion) ? setVkTxnVersion : undefined,
236
+ sendIsProof: permToString(perms?.send) === 'Proof',
237
+ editStateIsProof: permToString(perms?.editState) === 'Proof',
238
+ };
239
+ }
240
+ catch (err) {
241
+ return { accountFound: false, fetchError: err?.message ?? String(err) };
242
+ }
243
+ }
244
+ async function loadCanonicalVkHashes() {
245
+ try {
246
+ const m = await import('./contractInterface.js');
247
+ return m.CANONICAL_VK_HASHES ?? null;
248
+ }
249
+ catch {
250
+ return null;
251
+ }
252
+ }
253
+ export async function verifyTrustAnchor(opts) {
254
+ const origin = normalizeOrigin(opts.origin);
255
+ const address = opts.address;
256
+ const findings = [];
257
+ const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
258
+ // 1. manifest_fetch
259
+ const fetchResult = await fetchManifest(origin, address, timeoutMs);
260
+ findings.push({ name: fetchResult.name, ok: fetchResult.ok, detail: fetchResult.detail });
261
+ if (!fetchResult.ok) {
262
+ return { ok: false, origin, address, findings };
263
+ }
264
+ const { signature, payload } = splitManifest(fetchResult.body);
265
+ // 2. manifest_signature
266
+ if (!signature || !payload) {
267
+ findings.push({ name: 'manifest_signature', ok: false, detail: 'manifest missing signature or payload fields' });
268
+ return { ok: false, origin, address, findings };
269
+ }
270
+ const sigOk = await verifyManifestSignature(payload, signature, opts.pinnedPublicKeysBase64);
271
+ findings.push({
272
+ name: 'manifest_signature',
273
+ ok: sigOk,
274
+ detail: sigOk
275
+ ? `Ed25519 verified against pinned key (1 of ${opts.pinnedPublicKeysBase64.length})`
276
+ : 'signature does not verify against any pinned key',
277
+ });
278
+ if (!sigOk) {
279
+ return { ok: false, origin, address, findings };
280
+ }
281
+ // appId is trusted only after signature verifies — it comes from the signed
282
+ // payload, not the caller.
283
+ const appId = payload.appId;
284
+ // 3. manifest_address_in_generations
285
+ const entry = payload.generations.find((g) => g.zkAppAddress === address);
286
+ findings.push({
287
+ name: 'manifest_address_in_generations',
288
+ ok: !!entry,
289
+ detail: entry
290
+ ? `address maps to gen ${entry.gen} (${entry.status})`
291
+ : `address ${address} not in manifest generations for app "${appId}"`,
292
+ });
293
+ const generation = entry?.gen;
294
+ // 3b. manifest_matches_backend (opt-in)
295
+ if (opts.crossCheck) {
296
+ findings.push(await checkBackendMatch({
297
+ address,
298
+ vendorPayload: payload,
299
+ pinnedPublicKeysBase64: opts.pinnedPublicKeysBase64,
300
+ timeoutMs,
301
+ }));
302
+ }
303
+ if (opts.skipChainChecks) {
304
+ const allOk = findings.every((f) => f.ok);
305
+ return { ok: allOk, origin, appId, address, generation, findings };
306
+ }
307
+ if (!opts.minaGraphqlUrl) {
308
+ findings.push({ name: 'chain_account_exists', ok: false, detail: 'minaGraphqlUrl is required for chain checks' });
309
+ return { ok: false, origin, appId, address, generation, findings };
310
+ }
311
+ // 4-11: chain reads
312
+ const state = await readChainState(address, opts.minaGraphqlUrl, opts.minaNetworkId ?? 'mainnet');
313
+ findings.push({
314
+ name: 'chain_account_exists',
315
+ ok: state.accountFound,
316
+ detail: state.accountFound ? `account ${address.slice(0, 12)}… found` : (state.fetchError ?? 'account not found'),
317
+ });
318
+ if (!state.accountFound) {
319
+ return { ok: false, origin, appId, address, generation, findings };
320
+ }
321
+ const onChainOrigin = state.zkappUri ? urlOrigin(state.zkappUri) : null;
322
+ const originClean = urlOrigin(origin);
323
+ const uriOk = !!state.zkappUri && !!onChainOrigin && !!originClean && onChainOrigin === originClean;
324
+ findings.push({
325
+ name: 'chain_zkapp_uri_match',
326
+ ok: uriOk,
327
+ detail: state.zkappUri
328
+ ? (uriOk ? `zkappUri "${state.zkappUri}" origin matches` : `zkappUri "${state.zkappUri}" origin ≠ "${originClean ?? origin}"`)
329
+ : 'zkappUri is empty on chain',
330
+ });
331
+ const canonicalVks = await loadCanonicalVkHashes();
332
+ const expectedVk = generation !== undefined ? canonicalVks?.[generation] : undefined;
333
+ const vkOk = !!state.vkHash && !!expectedVk && state.vkHash === expectedVk;
334
+ findings.push({
335
+ name: 'chain_vk_hash_pinned',
336
+ ok: vkOk,
337
+ detail: vkOk
338
+ ? `gen ${generation} hash matches CANONICAL_VK_HASHES[${generation}]`
339
+ : !expectedVk
340
+ ? `no CANONICAL_VK_HASHES entry for gen ${generation ?? '?'}`
341
+ : `on-chain vkHash "${state.vkHash?.slice(0, 16)}…" ≠ pinned "${expectedVk.slice(0, 16)}…"`,
342
+ });
343
+ findings.push({
344
+ name: 'chain_set_zkapp_uri_impossible',
345
+ ok: !!state.setZkappUriIsImpossible,
346
+ detail: state.setZkappUriIsImpossible
347
+ ? 'permissions.setZkappUri = impossible (zkappUri is frozen)'
348
+ : 'permissions.setZkappUri ≠ impossible — vendor could rewrite the URI',
349
+ });
350
+ // The meta-freeze: without this, every other permission lock below is
351
+ // reversible with a single signature. Priority #1 among the extras.
352
+ findings.push({
353
+ name: 'chain_set_permissions_impossible',
354
+ ok: !!state.setPermissionsIsImpossible,
355
+ detail: state.setPermissionsIsImpossible
356
+ ? 'permissions.setPermissions = impossible (permission matrix is meta-frozen)'
357
+ : 'permissions.setPermissions ≠ impossible — every other lock could be relaxed later',
358
+ });
359
+ // setVerificationKey lock, with hardfork-aware softening.
360
+ //
361
+ // The contract deploys with VerificationKey.impossibleDuringCurrentVersion(),
362
+ // which stores {auth: Impossible, txnVersion: <chain's txnVersion at deploy
363
+ // time>}. After a Mina hardfork the chain's current txnVersion advances
364
+ // past the stored value and the effective enforcement falls back to
365
+ // signature() — but the deploy key was discarded (LicensingApp.ts:546-547),
366
+ // so no one can sign the fallback update.
367
+ //
368
+ // The keeper records the deploy-time txnVersion in the signed manifest as
369
+ // deployTxnVersion. We accept two states as OK, provided the on-chain
370
+ // stored txnVersion still matches the manifest-recorded value (which proves
371
+ // no one has re-set the permission since deploy):
372
+ //
373
+ // - auth = Impossible → normal, pre-hardfork state
374
+ // - auth = Signature → post-hardfork fallback (see above)
375
+ //
376
+ // Any mismatch — different txnVersion, or auth is some other string, or
377
+ // deployTxnVersion missing from an old manifest — falls back to the strict
378
+ // rule (auth === 'Impossible').
379
+ const onChainAuth = state.setVerificationKeyAuth;
380
+ const onChainTxnVersion = state.setVerificationKeyTxnVersion;
381
+ const manifestDeployTxnVersion = entry?.deployTxnVersion;
382
+ let vkLockOk = false;
383
+ let vkLockDetail;
384
+ if (manifestDeployTxnVersion !== undefined && onChainTxnVersion !== undefined && onChainTxnVersion === manifestDeployTxnVersion) {
385
+ if (onChainAuth === 'Impossible') {
386
+ vkLockOk = true;
387
+ vkLockDetail = `permissions.setVerificationKey.auth = impossible (circuit cannot be swapped; txnVersion ${onChainTxnVersion} matches deploy)`;
388
+ }
389
+ else if (onChainAuth === 'Signature') {
390
+ vkLockOk = true;
391
+ vkLockDetail = `permissions.setVerificationKey.auth = signature (post-hardfork fallback; deploy key was destroyed at deploy time; txnVersion ${onChainTxnVersion} matches deploy)`;
392
+ }
393
+ else {
394
+ vkLockDetail = `permissions.setVerificationKey.auth = "${onChainAuth ?? '?'}" — expected impossible or signature`;
395
+ }
396
+ }
397
+ else if (manifestDeployTxnVersion === undefined) {
398
+ // Older manifest without deployTxnVersion — fall back to strict.
399
+ vkLockOk = onChainAuth === 'Impossible';
400
+ vkLockDetail = vkLockOk
401
+ ? 'permissions.setVerificationKey.auth = impossible (circuit cannot be swapped; manifest omits deployTxnVersion — strict rule applied)'
402
+ : `permissions.setVerificationKey.auth = "${onChainAuth ?? '?'}" ≠ impossible — vendor could swap the circuit (manifest omits deployTxnVersion — strict rule applied)`;
403
+ }
404
+ else {
405
+ vkLockDetail = `on-chain setVerificationKey.txnVersion (${onChainTxnVersion ?? 'unknown'}) ≠ manifest deployTxnVersion (${manifestDeployTxnVersion}) — permission may have been re-set since deploy`;
406
+ }
407
+ findings.push({
408
+ name: 'chain_set_verification_key_locked',
409
+ ok: vkLockOk,
410
+ detail: vkLockDetail,
411
+ });
412
+ // send + editState must be proof() (not signature()): withdrawals and Merkle
413
+ // root advances only happen via a valid LicensingApp proof.
414
+ findings.push({
415
+ name: 'chain_send_proof_only',
416
+ ok: !!state.sendIsProof,
417
+ detail: state.sendIsProof
418
+ ? 'permissions.send = proof() (escrow only leaves via a refund proof)'
419
+ : 'permissions.send ≠ proof() — vendor could drain escrow with a signature',
420
+ });
421
+ findings.push({
422
+ name: 'chain_edit_state_proof_only',
423
+ ok: !!state.editStateIsProof,
424
+ detail: state.editStateIsProof
425
+ ? 'permissions.editState = proof() (Merkle root advances only via a proof)'
426
+ : 'permissions.editState ≠ proof() — vendor could rewrite the license root',
427
+ });
428
+ const allOk = findings.every((f) => f.ok);
429
+ return { ok: allOk, origin, appId, address, generation, findings };
430
+ }
431
+ //# sourceMappingURL=trustAnchorVerify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trustAnchorVerify.js","sourceRoot":"","sources":["../src/trustAnchorVerify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * trustAnchorVerifyCli.ts
4
+ *
5
+ * Command-line front-end for verifyTrustAnchor(). Ships as the `zklicensing-verify-trust`
6
+ * bin — the sibling of `zklicensing-verify` (which is the verifyService HTTP daemon).
7
+ *
8
+ * Usage:
9
+ * zklicensing-verify-trust \
10
+ * --origin https://store.example.com \
11
+ * --address B62q... \
12
+ * --pinned-key <base64-ed25519-pubkey> \
13
+ * [--mina-graphql https://api.minascan.io/node/mainnet/v1/graphql] \
14
+ * [--mina-network-id mainnet|testnet|devnet] \
15
+ * [--skip-chain-checks] \
16
+ * [--json]
17
+ *
18
+ * The manifest lives at `<origin>/.well-known/zklicensing/<address>.json` —
19
+ * one file per generation address, all signed by the same platform key. The
20
+ * appId is read out of the signed payload; callers never need to know it
21
+ * out-of-band, which lets buyers verify from just the address their wallet
22
+ * shows them (including addresses for retired generations).
23
+ *
24
+ * Exit codes:
25
+ * 0 — every finding passed
26
+ * 1 — one or more findings failed
27
+ * 2 — invalid arguments
28
+ *
29
+ * --pinned-key is required and may be repeated; the CLI ships NO baked-in
30
+ * pin. Source it from https://zklicensing.com/trustanchor.html (published
31
+ * next to each generation's VK hash). See the SDK README for details.
32
+ */
33
+ import { type Finding } from './trustAnchorVerify.js';
34
+ export type { Finding };
35
+ //# sourceMappingURL=trustAnchorVerifyCli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trustAnchorVerifyCli.d.ts","sourceRoot":"","sources":["../src/trustAnchorVerifyCli.ts"],"names":[],"mappings":";AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAqB,KAAK,OAAO,EAA0B,MAAM,wBAAwB,CAAC;AA8IjG,YAAY,EAAE,OAAO,EAAE,CAAC"}