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 @@
1
+ {"version":3,"file":"licenseRecord.d.ts","sourceRoot":"","sources":["../src/licenseRecord.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAQH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAI,MAAM,CAAC;IACtB,WAAW,EAAI,MAAM,CAAC;IACtB,WAAW,EAAI,MAAM,CAAC;IACtB,UAAU,EAAK,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAI,MAAM,CAAC;IACvB,WAAW,EAAK,MAAM,CAAC;IACvB,UAAU,EAAM,MAAM,CAAC;IACvB,YAAY,EAAI,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAU,MAAM,CAAC;IACvB,SAAS,EAAO,MAAM,CAAC;IAMvB,SAAS,CAAC,EAAQ,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAI3B,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,SAAS,EAAS,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAO,MAAM,CAAC;QACzB,WAAW,EAAO,MAAM,CAAC;KAC1B,CAAC,CAAC;IACH,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAO,MAAM,CAAC;IACvB,OAAO,CAAC,EAAQ,OAAO,CAAC;IACxB,YAAY,CAAC,EAAG,MAAM,CAAC;IAGvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;IAGvD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAG7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAKrB,aAAa,CAAC,EAAE,MAAM,CAAC;IAOvB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAKxH,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAMhC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAMhC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAIF,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC"}
@@ -1,5 +1,5 @@
1
1
  // Copyright (c) 2025-2026 zkLicensing project developers
2
- // All rights reserved.
2
+ // SPDX-License-Identifier: BUSL-1.1
3
3
  // Reap pending records this many slots after prove time if no event ever lands.
4
4
  // 60 slots ≈ 90 minutes — a generous window for tx inclusion under devnet conditions.
5
5
  export const PENDING_REAP_SLOTS = 60;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseRecord.js","sourceRoot":"","sources":["../src/licenseRecord.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,oCAAoC;AAsGpC,gFAAgF;AAChF,sFAAsF;AACtF,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC"}
@@ -34,15 +34,30 @@ export declare function updateExpiry(zkAppAddress: string, licenseHash: string,
34
34
  };
35
35
  }): Promise<boolean>;
36
36
  export declare function recordRefund(zkAppAddress: string, licenseHash: string): Promise<boolean>;
37
- export declare function recordRelease(zkAppAddress: string, licenseHash: string, releaseSlot?: number): Promise<boolean>;
37
+ export declare function recordRelease(zkAppAddress: string, licenseHash: string, releaseSlot?: number, txHash?: string): Promise<boolean>;
38
38
  export declare function confirmRecord(zkAppAddress: string, licenseHash: string): Promise<boolean>;
39
39
  export declare function applyLicenseIssued(zkAppAddress: string, licenseHash: string, fields: {
40
40
  expirySlot: number;
41
41
  purchaseSlot: number;
42
42
  purchaseAmount: string;
43
- tier?: 'monthly' | 'yearly' | 'fiveYear';
43
+ tier?: 'monthly' | 'yearly' | 'fiveYear' | 'perpetual';
44
44
  escrowless?: boolean;
45
+ deviceCap?: number;
46
+ deviceSlotsRoot?: string;
47
+ deviceSlotsFilled?: number;
45
48
  }): Promise<void>;
49
+ export declare function applyLicenseRenewed(zkAppAddress: string, licenseHash: string, fields: {
50
+ newExpiry: number;
51
+ }): Promise<boolean>;
52
+ export declare function applyDeviceBound(zkAppAddress: string, licenseHash: string, fields: {
53
+ slotIndex: number;
54
+ deviceCommitment: string;
55
+ boundAtSlot: number;
56
+ }): Promise<boolean>;
57
+ export declare function applyDeviceUnbound(zkAppAddress: string, licenseHash: string, fields: {
58
+ slotIndex: number;
59
+ freedAtSlot: number;
60
+ }): Promise<boolean>;
46
61
  export declare function deleteRecord(zkAppAddress: string, licenseHash: string): Promise<boolean>;
47
62
  export declare function getStalePendingRecords(currentSlot: number, maxAgeSlots?: number): Promise<LicenseRecord[]>;
48
63
  export declare function getReleasableRecords(currentSlot: number): Promise<LicenseRecord[]>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseStore.d.ts","sourceRoot":"","sources":["../src/licenseStore.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  // Copyright (c) 2025-2026 zkLicensing project developers
2
- // All rights reserved.
2
+ // SPDX-License-Identifier: BUSL-1.1
3
3
  /**
4
4
  * licenseStore.ts
5
5
  *
@@ -13,11 +13,11 @@
13
13
  * Used by:
14
14
  * - interact.ts / buyLicense.ts (CLI) — reads/writes directly
15
15
  * - keeperService.ts — exposes the same logic over HTTP
16
- * - proofServer.ts — reads expirySlot for a given licenseHash
17
16
  */
18
17
  import fs from 'fs/promises';
19
18
  import { Bool, Field, MerkleMap, MerkleMapWitness, Poseidon, PublicKey, UInt32, UInt64 } from 'o1js';
20
19
  import { GRACE_PERIOD_N, REFUND_WINDOW_N } from './contractInterface.js';
20
+ import { computeDeviceSlotsRoot, DEVICE_SLOT_CAP_N, leafFromRecord, leafHash } from './licenseLeaf.js';
21
21
  import { PENDING_REAP_SLOTS as _PENDING_REAP_SLOTS } from './licenseRecord.js';
22
22
  export const PENDING_REAP_SLOTS = _PENDING_REAP_SLOTS;
23
23
  export function licenseStorePath() {
@@ -64,12 +64,19 @@ function recordsForApp(records, zkAppAddress) {
64
64
  return records.filter(r => r.zkAppAddress === zkAppAddress);
65
65
  }
66
66
  // Rebuild the license MerkleMap for a single zkApp. Only inserts entries
67
- // with expirySlot > 0.
67
+ // with expirySlot > 0. The value stored at each key is `leaf.hash()` — the
68
+ // Poseidon commitment over (licenseHash, expirySlot, cap, deviceSlotsRoot,
69
+ // deviceSlotsFilled) — matching what LicensingApp writes. Records that
70
+ // predate device binding rebuild to a leaf with empty slots (see
71
+ // leafFromRecord for the exact defaults); on those records the rebuilt
72
+ // root matches what the old contract wrote, but any mutation call will
73
+ // fail the in-circuit hash check until the missing fields are backfilled
74
+ // from chain events.
68
75
  export function buildMap(records, zkAppAddress) {
69
76
  const map = new MerkleMap();
70
77
  for (const r of recordsForApp(records, zkAppAddress)) {
71
78
  if (r.expirySlot !== 0) {
72
- map.set(Field(r.licenseHash), Field(r.expirySlot));
79
+ map.set(Field(r.licenseHash), leafHash(leafFromRecord(r)));
73
80
  }
74
81
  }
75
82
  return map;
@@ -138,6 +145,15 @@ export async function upsertLicense(record) {
138
145
  if (!record.zkAppAddress) {
139
146
  throw new Error('upsertLicense: record.zkAppAddress is required');
140
147
  }
148
+ // Populate the empty-slot mirror at insert time when the license is capped.
149
+ // Without this, /confirm/buy writes deviceCap:N but leaves deviceSlotsRoot
150
+ // and deviceSlotsFilled undefined until the first bind — leafFromRecord's
151
+ // fallbacks paper over it for hash reconstruction, but every consumer that
152
+ // reads the mirror directly (preflight logs, /license responses, offline
153
+ // verify) would see undefined and either misreport or need its own fallback.
154
+ if ((record.deviceCap ?? 0) > 0 && (record.deviceSlotsRoot === undefined || record.deviceSlotsFilled === undefined)) {
155
+ refreshSlotMirror(record);
156
+ }
141
157
  return withWriteLock(async () => {
142
158
  const records = await readRecords();
143
159
  const idx = records.findIndex(r => r.zkAppAddress === record.zkAppAddress && r.licenseHash === record.licenseHash);
@@ -187,6 +203,12 @@ export async function recordRefund(zkAppAddress, licenseHash) {
187
203
  record.purchaseSlot = 0;
188
204
  record.purchaseAmount = '0';
189
205
  record.refunded = true;
206
+ // Same pending-clear the buy/renew apply* siblings do — /confirm/refund
207
+ // wrote pending:true optimistically; the on-chain event landing is what
208
+ // authorizes clearing it. Without this the SDK poller (which requires
209
+ // pending===false && status==='refunded') hangs forever.
210
+ delete record.pending;
211
+ delete record.provedAtSlot;
190
212
  await writeRecords(records);
191
213
  return true;
192
214
  });
@@ -194,7 +216,7 @@ export async function recordRefund(zkAppAddress, licenseHash) {
194
216
  // Mark escrow as released. Preserves purchaseAmount/purchaseSlot so stats can
195
217
  // compute released revenue. The `released` flag is the truth signal —
196
218
  // buildEscrowMap and getReleasableRecords filter on it directly.
197
- export async function recordRelease(zkAppAddress, licenseHash, releaseSlot) {
219
+ export async function recordRelease(zkAppAddress, licenseHash, releaseSlot, txHash) {
198
220
  return withWriteLock(async () => {
199
221
  const records = await readRecords();
200
222
  const record = records.find(r => r.zkAppAddress === zkAppAddress && r.licenseHash === licenseHash);
@@ -203,6 +225,8 @@ export async function recordRelease(zkAppAddress, licenseHash, releaseSlot) {
203
225
  record.released = true;
204
226
  if (releaseSlot !== undefined)
205
227
  record.releaseSlot = releaseSlot;
228
+ if (txHash !== undefined)
229
+ record.releaseTxHash = txHash;
206
230
  await writeRecords(records);
207
231
  return true;
208
232
  });
@@ -252,9 +276,23 @@ export async function applyLicenseIssued(zkAppAddress, licenseHash, fields) {
252
276
  record.escrowless = true;
253
277
  dirty = true;
254
278
  }
279
+ // Backfill leaf fields if the record was created before the event
280
+ // carried them, or if a prior partial rehydrate is still missing them.
281
+ if (fields.deviceCap !== undefined && record.deviceCap === undefined) {
282
+ record.deviceCap = fields.deviceCap;
283
+ dirty = true;
284
+ }
285
+ if (fields.deviceSlotsRoot !== undefined && record.deviceSlotsRoot === undefined) {
286
+ record.deviceSlotsRoot = fields.deviceSlotsRoot;
287
+ dirty = true;
288
+ }
289
+ if (fields.deviceSlotsFilled !== undefined && record.deviceSlotsFilled === undefined) {
290
+ record.deviceSlotsFilled = fields.deviceSlotsFilled;
291
+ dirty = true;
292
+ }
255
293
  }
256
294
  else {
257
- records.push({
295
+ const inserted = {
258
296
  zkAppAddress,
259
297
  licenseHash,
260
298
  expirySlot: fields.expirySlot,
@@ -265,13 +303,135 @@ export async function applyLicenseIssued(zkAppAddress, licenseHash, fields) {
265
303
  initialExpirySlot: fields.expirySlot,
266
304
  ...(fields.tier ? { tier: fields.tier } : {}),
267
305
  ...(fields.escrowless === true ? { escrowless: true } : {}),
268
- });
306
+ ...(fields.deviceCap !== undefined ? { deviceCap: fields.deviceCap } : {}),
307
+ ...(fields.deviceSlotsRoot !== undefined ? { deviceSlotsRoot: fields.deviceSlotsRoot } : {}),
308
+ ...(fields.deviceSlotsFilled !== undefined ? { deviceSlotsFilled: fields.deviceSlotsFilled } : {}),
309
+ };
310
+ // Same rationale as upsertLicense: populate the empty-slot mirror on
311
+ // first insert so the record is immediately queryable without relying
312
+ // on leafFromRecord's undefined fallbacks.
313
+ if ((inserted.deviceCap ?? 0) > 0 && (inserted.deviceSlotsRoot === undefined || inserted.deviceSlotsFilled === undefined)) {
314
+ refreshSlotMirror(inserted);
315
+ }
316
+ records.push(inserted);
269
317
  dirty = true;
270
318
  }
271
319
  if (dirty)
272
320
  await writeRecords(records);
273
321
  });
274
322
  }
323
+ // Apply a licenseRenewed event atomically: clear any pending /confirm/renew
324
+ // write, align expirySlot with the event, and flip renewedAtLeastOnce.
325
+ // Symmetric to applyLicenseIssued — the archive-events path is what closes
326
+ // out a renew that the bestChain sweep missed (tx landed after the sweep's
327
+ // BESTCHAIN_DEPTH window rolled past), and without a pending-clear step here
328
+ // the flag on a landed record could be stuck forever.
329
+ //
330
+ // Does NOT append to renewals[] — that log is populated at /confirm/renew
331
+ // time from the intent (which carries amount + txHash); the archive event
332
+ // carries only newExpiry, so replaying it must not overwrite the richer
333
+ // confirm-time entry.
334
+ export async function applyLicenseRenewed(zkAppAddress, licenseHash, fields) {
335
+ return withWriteLock(async () => {
336
+ const records = await readRecords();
337
+ const record = records.find(r => r.zkAppAddress === zkAppAddress && r.licenseHash === licenseHash);
338
+ if (!record)
339
+ return false;
340
+ let dirty = false;
341
+ if (record.pending) {
342
+ delete record.pending;
343
+ delete record.provedAtSlot;
344
+ dirty = true;
345
+ }
346
+ if (record.expirySlot !== fields.newExpiry) {
347
+ record.expirySlot = fields.newExpiry;
348
+ dirty = true;
349
+ }
350
+ if (!record.renewedAtLeastOnce) {
351
+ record.renewedAtLeastOnce = true;
352
+ dirty = true;
353
+ }
354
+ if (dirty)
355
+ await writeRecords(records);
356
+ return true;
357
+ });
358
+ }
359
+ // Recompute deviceSlotsRoot + deviceSlotsFilled from the record's mirror after
360
+ // a bind/unbind mutation. `leafFromRecord` uses those two persisted fields when
361
+ // building the on-chain leaf hash; if they drift from the on-chain state the
362
+ // next mutation call fails the in-circuit leaf-hash assert. Mirror the exact
363
+ // packing the circuit uses (packSlotTimes: freedAt in low 32 bits, boundAt in
364
+ // high 32) so the fold matches the on-chain deviceSlotsRoot bit-for-bit.
365
+ function refreshSlotMirror(record) {
366
+ const devices = record.devices ?? [];
367
+ const occupied = [];
368
+ const freedAt = [];
369
+ for (let i = 0; i < DEVICE_SLOT_CAP_N; i++) {
370
+ const entry = devices.find(d => d.slotIndex === i);
371
+ const occ = entry?.deviceCommitment ?? '0';
372
+ occupied.push(Field(occ));
373
+ const boundAt = BigInt(entry?.boundAtSlot ?? 0);
374
+ const freed = BigInt(entry?.freedAtSlot ?? 0);
375
+ // packSlotTimes(boundAt, freedAt) in licenseLeaf.ts: freedAt low 32, boundAt high 32.
376
+ const packed = freed + (boundAt << 32n);
377
+ freedAt.push(Field(packed));
378
+ }
379
+ record.deviceSlotsRoot = computeDeviceSlotsRoot(occupied, freedAt).toString();
380
+ record.deviceSlotsFilled = devices.filter(d => d.deviceCommitment !== '0').length;
381
+ }
382
+ // Apply a deviceBound event atomically: mirrors the on-chain slot mutation
383
+ // into the record.devices[] array and recomputes deviceSlotsRoot / filled so
384
+ // leafFromRecord reconstructs the exact leaf hash the chain committed.
385
+ //
386
+ // `boundAtSlot` MUST be the circuit's proof-time `globalSlotSinceGenesis` (the
387
+ // value emitted in `DeviceBoundEvent.boundAtSlot`). The block slot when the tx
388
+ // landed is NOT interchangeable: TOLERANCE_WINDOW allows them to differ, and
389
+ // any drift flips the packed `freedAt` field → wrong leaf → root divergence.
390
+ export async function applyDeviceBound(zkAppAddress, licenseHash, fields) {
391
+ return withWriteLock(async () => {
392
+ const records = await readRecords();
393
+ const record = records.find(r => r.zkAppAddress === zkAppAddress && r.licenseHash === licenseHash);
394
+ if (!record)
395
+ return false;
396
+ const devices = (record.devices ??= []);
397
+ // Ensure the array is long enough — pad with empty slots.
398
+ while (devices.length <= fields.slotIndex) {
399
+ devices.push({ slotIndex: devices.length, deviceCommitment: '0', boundAtSlot: 0, freedAtSlot: 0 });
400
+ }
401
+ devices[fields.slotIndex] = {
402
+ slotIndex: fields.slotIndex,
403
+ deviceCommitment: fields.deviceCommitment,
404
+ boundAtSlot: fields.boundAtSlot,
405
+ freedAtSlot: 0, // pristine → fresh bind resets freedAt
406
+ };
407
+ refreshSlotMirror(record);
408
+ await writeRecords(records);
409
+ return true;
410
+ });
411
+ }
412
+ // Apply a deviceUnbound event atomically. Preserves boundAtSlot for audit,
413
+ // stamps freedAtSlot for the cooldown timer the circuit's next bind enforces.
414
+ //
415
+ // `freedAtSlot` MUST be the circuit's proof-time `globalSlotSinceGenesis` (the
416
+ // value emitted in `DeviceUnboundEvent.freedAtSlot`). Same reason as
417
+ // `applyDeviceBound.boundAtSlot`.
418
+ export async function applyDeviceUnbound(zkAppAddress, licenseHash, fields) {
419
+ return withWriteLock(async () => {
420
+ const records = await readRecords();
421
+ const record = records.find(r => r.zkAppAddress === zkAppAddress && r.licenseHash === licenseHash);
422
+ if (!record || !record.devices)
423
+ return false;
424
+ const slot = record.devices.find(d => d.slotIndex === fields.slotIndex);
425
+ if (!slot)
426
+ return false;
427
+ slot.deviceCommitment = '0';
428
+ slot.freedAtSlot = fields.freedAtSlot;
429
+ // boundAtSlot stays as the last bind time — historical / audit.
430
+ refreshSlotMirror(record);
431
+ await writeRecords(records);
432
+ return true;
433
+ });
434
+ }
275
435
  // Delete a record entirely (used to reap stale pending entries the buyer never submitted).
276
436
  export async function deleteRecord(zkAppAddress, licenseHash) {
277
437
  return withWriteLock(async () => {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseStore.js","sourceRoot":"","sources":["../src/licenseStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestVerify.d.ts","sourceRoot":"","sources":["../src/manifestVerify.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQnD;AA6BD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,MAAM,EACvB,sBAAsB,EAAE,SAAS,MAAM,EAAE,GACxC,OAAO,CAAC,OAAO,CAAC,CA+BlB"}
@@ -1,5 +1,5 @@
1
1
  // Copyright (c) 2025-2026 zkLicensing project developers
2
- // All rights reserved.
2
+ // SPDX-License-Identifier: BUSL-1.1
3
3
  /**
4
4
  * manifestVerify.ts
5
5
  *
@@ -21,6 +21,10 @@
21
21
  * simple and mirrored.
22
22
  */
23
23
  // Canonical JSON: sorted keys, no whitespace, arrays preserved in order.
24
+ // Undefined values are skipped, mirroring JSON.stringify — otherwise the
25
+ // signed bytes would contain `"key":undefined` for optional fields left
26
+ // unset, while `res.json()` on the wire would strip them, and the signature
27
+ // would never verify.
24
28
  // Mirror of src/manifestSign.ts:canonicalize. Divergence here silently
25
29
  // breaks verification.
26
30
  export function canonicalize(value) {
@@ -28,8 +32,9 @@ export function canonicalize(value) {
28
32
  return JSON.stringify(value);
29
33
  if (Array.isArray(value))
30
34
  return '[' + value.map(canonicalize).join(',') + ']';
31
- const keys = Object.keys(value).sort();
32
- return '{' + keys.map(k => JSON.stringify(k) + ':' + canonicalize(value[k])).join(',') + '}';
35
+ const obj = value;
36
+ const keys = Object.keys(obj).filter(k => obj[k] !== undefined).sort();
37
+ return '{' + keys.map(k => JSON.stringify(k) + ':' + canonicalize(obj[k])).join(',') + '}';
33
38
  }
34
39
  function base64ToBytes(b64) {
35
40
  // atob is present in every modern JS runtime we target (browser + Node ≥ 16).
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestVerify.js","sourceRoot":"","sources":["../src/manifestVerify.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,6 @@
1
- /**
2
- * migrateClient.ts
3
- *
4
- * Browser-safe client for /prove/migrate. Assembles a single-hop cross-
5
- * generation proof against the current live map — the keeper walks the
6
- * deploymentHistory once, gathers all three witnesses (ancestor / pred /
7
- * live-empty), and returns a signable tx.
8
- *
9
- * Failure surfaces:
10
- * - 404 "license refunded or unknown": no leaf anywhere in history for
11
- * this licenseHash. Caller should not retry — it's terminal.
12
- * - 409 "already migrated": leaf is present in the live map. Caller
13
- * should refresh their license record and stop.
14
- * - 409 "migration in flight": another caller is proving right now.
15
- * `retryAfterMs` on the error tells the caller how long to wait
16
- * before trying again. See `ProveMigrateError.retryAfterMs`.
17
- */
18
1
  export interface ProveMigrateRequest {
19
2
  keeperUrl: string;
3
+ network: 'devnet' | 'mainnet';
20
4
  licenseHash: string;
21
5
  appId: string;
22
6
  buyerAddress: string;
@@ -29,15 +13,16 @@ export interface ProveMigrateResponse {
29
13
  expirySlot: number;
30
14
  licenseHash: string;
31
15
  zkAppAddress: string;
16
+ appKey: string;
32
17
  }
33
18
  /**
34
- * Extends Error with the retryAfterMs hint the keeper returns on the
35
- * "migration in flight" 409. Callers ignore it for other 4xx surfaces.
19
+ * Terminal migrate failures (404 refunded/unknown, 409 already migrated).
20
+ * The queue-busy 409 is surfaced separately as ProveQueueBusyError so
21
+ * callers can share one retry helper across buy/renew/migrate.
36
22
  */
37
23
  export declare class ProveMigrateError extends Error {
38
24
  readonly status: number;
39
- readonly retryAfterMs?: number;
40
- constructor(message: string, status: number, retryAfterMs?: number);
25
+ constructor(message: string, status: number);
41
26
  }
42
27
  export declare function proveMigrate(req: ProveMigrateRequest): Promise<ProveMigrateResponse>;
43
28
  //# sourceMappingURL=migrateClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateClient.d.ts","sourceRoot":"","sources":["../src/migrateClient.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAK,MAAM,CAAC;IACrB,OAAO,EAAO,QAAQ,GAAG,SAAS,CAAC;IACnC,WAAW,EAAG,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAM,OAAO,KAAK,CAAC;IAC3B,MAAM,CAAC,EAAO,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,CAAC;IACrB,UAAU,EAAI,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IAGrB,MAAM,EAAQ,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK5C;AAMD,wBAAsB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAoB1F"}
@@ -1,17 +1,35 @@
1
1
  // Copyright (c) 2025-2026 zkLicensing project developers
2
- // All rights reserved.
2
+ // SPDX-License-Identifier: BUSL-1.1
3
3
  /**
4
- * Extends Error with the retryAfterMs hint the keeper returns on the
5
- * "migration in flight" 409. Callers ignore it for other 4xx surfaces.
4
+ * migrateClient.ts
5
+ *
6
+ * Browser-safe client for /prove/migrate. Assembles a single-hop cross-
7
+ * generation proof against the current live map — the keeper walks the
8
+ * deploymentHistory once, gathers all three witnesses (ancestor / pred /
9
+ * live-empty), and returns a signable tx.
10
+ *
11
+ * Failure surfaces:
12
+ * - 404 "license refunded or unknown": no leaf anywhere in history for
13
+ * this licenseHash. Caller should not retry — it's terminal.
14
+ * - 409 "already migrated": leaf is present in the live map. Caller
15
+ * should refresh their license record and stop.
16
+ * - 409 "proving queue busy": another root-mutating request (buy, renew,
17
+ * migrate) is holding this app's in-flight slot. Thrown as the shared
18
+ * ProveQueueBusyError so callers can wait+retry uniformly across the
19
+ * three endpoints.
20
+ */
21
+ import { readErrorBody, tryQueueBusyFromBody } from './proveErrors.js';
22
+ /**
23
+ * Terminal migrate failures (404 refunded/unknown, 409 already migrated).
24
+ * The queue-busy 409 is surfaced separately as ProveQueueBusyError so
25
+ * callers can share one retry helper across buy/renew/migrate.
6
26
  */
7
27
  export class ProveMigrateError extends Error {
8
28
  status;
9
- retryAfterMs;
10
- constructor(message, status, retryAfterMs) {
29
+ constructor(message, status) {
11
30
  super(message);
12
31
  this.name = 'ProveMigrateError';
13
32
  this.status = status;
14
- this.retryAfterMs = retryAfterMs;
15
33
  }
16
34
  }
17
35
  function baseUrl(url) {
@@ -24,23 +42,18 @@ export async function proveMigrate(req) {
24
42
  headers: { 'Content-Type': 'application/json' },
25
43
  signal: req.signal,
26
44
  body: JSON.stringify({
45
+ network: req.network,
27
46
  licenseHash: req.licenseHash,
28
47
  appId: req.appId,
29
48
  buyerAddress: req.buyerAddress,
30
49
  }),
31
50
  });
32
51
  if (!resp.ok) {
33
- let msg = `HTTP ${resp.status}`;
34
- let retryAfterMs;
35
- try {
36
- const body = await resp.json();
37
- if (typeof body.error === 'string')
38
- msg = body.error;
39
- if (typeof body.retryAfterMs === 'number')
40
- retryAfterMs = body.retryAfterMs;
41
- }
42
- catch { /* body wasn't JSON */ }
43
- throw new ProveMigrateError(msg, resp.status, retryAfterMs);
52
+ const parsed = await readErrorBody(resp);
53
+ const queueBusy = tryQueueBusyFromBody(parsed);
54
+ if (queueBusy)
55
+ throw queueBusy;
56
+ throw new ProveMigrateError(parsed.message, resp.status);
44
57
  }
45
58
  return await resp.json();
46
59
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateClient.js","sourceRoot":"","sources":["../src/migrateClient.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,oCAAoC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAuBvE;;;;GAIG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,MAAM,CAAS;IACxB,YAAY,OAAe,EAAE,MAAc;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAwB;IACzD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE;QACpE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAO,GAAG,CAAC,OAAO;YACzB,WAAW,EAAG,GAAG,CAAC,WAAW;YAC7B,KAAK,EAAS,GAAG,CAAC,KAAK;YACvB,YAAY,EAAE,GAAG,CAAC,YAAY;SAC/B,CAAC;KACH,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,SAAS;YAAE,MAAM,SAAS,CAAC;QAC/B,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,IAAI,CAAC,IAAI,EAA0B,CAAC;AACnD,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * onChainRoot.ts
3
+ *
4
+ * Non-custodial trust anchor for `verifyOffline`. Reads the live
5
+ * `licensesRoot` (`zkapp.appState[0]`) directly from Mina — no
6
+ * licensing-service round-trip, no trust assumption about whoever
7
+ * served the witness / license record.
8
+ *
9
+ * Pair it with `verifyOffline` to close the trust loop:
10
+ *
11
+ * ```ts
12
+ * import { fetchOnChainLicensesRoot } from 'zklicensing/on-chain-root';
13
+ * import { verifyOffline } from 'zklicensing/verify-offline';
14
+ *
15
+ * // 1. Ask the licensing service for a witness + slot snapshot.
16
+ * const snap = await fetch(`${service}/witness?licenseHash=${h}&zkAppAddress=${a}`).then(r => r.json());
17
+ *
18
+ * // 2. Fetch the on-chain root INDEPENDENTLY, from Mina.
19
+ * const onChainRoot = await fetchOnChainLicensesRoot({ zkAppAddress: a, network: 'devnet' });
20
+ *
21
+ * // 3. Cross-check — if they disagree, the service is stale/wrong; bail.
22
+ * if (snap.root !== onChainRoot) throw new Error('service root disagrees with chain');
23
+ *
24
+ * // 4. Fold-verify the snapshot against the on-chain root.
25
+ * const res = verifyOffline({ licensesRoot: onChainRoot, ...snap });
26
+ * ```
27
+ *
28
+ * o1js is a peer dep — this file imports it dynamically so callers
29
+ * that only want `verifyOffline` (pure fold, no chain read) don't
30
+ * have to install o1js.
31
+ *
32
+ * Global-state caveat: o1js `Mina.setActiveInstance` mutates a module-
33
+ * scoped singleton. Long-lived hosts that talk to multiple Mina
34
+ * networks in the same process should treat this helper as a
35
+ * one-shot and re-set their own preferred network after use, or wrap
36
+ * it in a mutex.
37
+ */
38
+ export declare const DEFAULT_MINA_GRAPHQL_URLS: {
39
+ readonly mainnet: "https://api.minascan.io/node/mainnet/v1/graphql";
40
+ readonly devnet: "https://api.minascan.io/node/devnet/v1/graphql";
41
+ };
42
+ export type NetworkName = 'mainnet' | 'devnet';
43
+ export type FetchOnChainLicensesRootInput = {
44
+ /** B62q… address of the deployed LicensingApp for this app. */
45
+ zkAppAddress: string;
46
+ } & ({
47
+ network: NetworkName;
48
+ graphqlUrl?: string;
49
+ } | {
50
+ graphqlUrl: string;
51
+ network?: NetworkName;
52
+ });
53
+ /**
54
+ * Read the live `licensesRoot` from the deployed LicensingApp's
55
+ * on-chain state. Returns the field value as a decimal string,
56
+ * matching the shape `verifyOffline` and the licensing service both
57
+ * consume.
58
+ *
59
+ * Throws on any of:
60
+ * - `o1js` not installed (peer dep missing);
61
+ * - `fetchAccount` returned an error (network down, wrong endpoint,
62
+ * account doesn't exist on this chain);
63
+ * - account exists but has no zkApp state (not a zkApp address, or
64
+ * contract deployed but `initialize()` never ran).
65
+ */
66
+ export declare function fetchOnChainLicensesRoot(input: FetchOnChainLicensesRootInput): Promise<string>;
67
+ //# sourceMappingURL=onChainRoot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onChainRoot.d.ts","sourceRoot":"","sources":["../src/onChainRoot.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH,eAAO,MAAM,yBAAyB;;;CAG5B,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE/C,MAAM,MAAM,6BAA6B,GAAG;IAC1C,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,CACA;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,CAAA;CAAE,CAChD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,MAAM,CAAC,CAgCjB"}