@haverstack/core 0.41.0 → 0.43.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.
Files changed (317) hide show
  1. package/README.md +124 -64
  2. package/dist/access.d.ts +43 -47
  3. package/dist/access.d.ts.map +1 -1
  4. package/dist/access.js +66 -101
  5. package/dist/access.js.map +1 -1
  6. package/dist/{combine.d.ts → adapter/combine.d.ts} +8 -1
  7. package/dist/adapter/combine.d.ts.map +1 -0
  8. package/dist/{combine.js → adapter/combine.js} +18 -3
  9. package/dist/adapter/combine.js.map +1 -0
  10. package/dist/adapter/index.d.ts +19 -0
  11. package/dist/adapter/index.d.ts.map +1 -0
  12. package/dist/adapter/index.js +16 -0
  13. package/dist/adapter/index.js.map +1 -0
  14. package/dist/adapter/reach.d.ts +14 -0
  15. package/dist/adapter/reach.d.ts.map +1 -0
  16. package/dist/adapter/reach.js +31 -0
  17. package/dist/adapter/reach.js.map +1 -0
  18. package/dist/{sort.d.ts → adapter/sort.d.ts} +20 -20
  19. package/dist/adapter/sort.d.ts.map +1 -0
  20. package/dist/{sort.js → adapter/sort.js} +37 -27
  21. package/dist/adapter/sort.js.map +1 -0
  22. package/dist/associations/identity.d.ts +69 -0
  23. package/dist/associations/identity.d.ts.map +1 -0
  24. package/dist/associations/identity.js +174 -0
  25. package/dist/associations/identity.js.map +1 -0
  26. package/dist/associations/validation.d.ts +83 -0
  27. package/dist/associations/validation.d.ts.map +1 -0
  28. package/dist/associations/validation.js +312 -0
  29. package/dist/associations/validation.js.map +1 -0
  30. package/dist/attachment-records.d.ts +48 -0
  31. package/dist/attachment-records.d.ts.map +1 -0
  32. package/dist/attachment-records.js +52 -0
  33. package/dist/attachment-records.js.map +1 -0
  34. package/dist/collection.d.ts +178 -0
  35. package/dist/collection.d.ts.map +1 -0
  36. package/dist/collection.js +397 -0
  37. package/dist/collection.js.map +1 -0
  38. package/dist/content-match.d.ts +25 -0
  39. package/dist/content-match.d.ts.map +1 -0
  40. package/dist/content-match.js +51 -0
  41. package/dist/content-match.js.map +1 -0
  42. package/dist/content-translation.d.ts +42 -0
  43. package/dist/content-translation.d.ts.map +1 -0
  44. package/dist/content-translation.js +108 -0
  45. package/dist/content-translation.js.map +1 -0
  46. package/dist/did/did.d.ts.map +1 -0
  47. package/dist/{did.js → did/did.js} +3 -4
  48. package/dist/did/did.js.map +1 -0
  49. package/dist/{did-entry.d.ts → did/index.d.ts} +1 -1
  50. package/dist/did/index.d.ts.map +1 -0
  51. package/dist/{did-entry.js → did/index.js} +3 -3
  52. package/dist/did/index.js.map +1 -0
  53. package/dist/errors.d.ts +54 -66
  54. package/dist/errors.d.ts.map +1 -1
  55. package/dist/errors.js +58 -62
  56. package/dist/errors.js.map +1 -1
  57. package/dist/grants.d.ts +20 -44
  58. package/dist/grants.d.ts.map +1 -1
  59. package/dist/grants.js +69 -151
  60. package/dist/grants.js.map +1 -1
  61. package/dist/id.d.ts +13 -31
  62. package/dist/id.d.ts.map +1 -1
  63. package/dist/id.js +13 -31
  64. package/dist/id.js.map +1 -1
  65. package/dist/index.d.ts +13 -9
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +9 -6
  68. package/dist/index.js.map +1 -1
  69. package/dist/install.d.ts +3 -6
  70. package/dist/install.d.ts.map +1 -1
  71. package/dist/install.js +6 -10
  72. package/dist/install.js.map +1 -1
  73. package/dist/lazy.d.ts +13 -0
  74. package/dist/lazy.d.ts.map +1 -0
  75. package/dist/lazy.js +27 -0
  76. package/dist/lazy.js.map +1 -0
  77. package/dist/merge.d.ts +1 -1
  78. package/dist/merge.d.ts.map +1 -1
  79. package/dist/merge.js +6 -12
  80. package/dist/merge.js.map +1 -1
  81. package/dist/migration-steps.d.ts +102 -0
  82. package/dist/migration-steps.d.ts.map +1 -0
  83. package/dist/migration-steps.js +293 -0
  84. package/dist/migration-steps.js.map +1 -0
  85. package/dist/query-validation.d.ts +68 -121
  86. package/dist/query-validation.d.ts.map +1 -1
  87. package/dist/query-validation.js +214 -380
  88. package/dist/query-validation.js.map +1 -1
  89. package/dist/record-changes.d.ts +11 -150
  90. package/dist/record-changes.d.ts.map +1 -1
  91. package/dist/record-changes.js +14 -305
  92. package/dist/record-changes.js.map +1 -1
  93. package/dist/schema.d.ts +18 -7
  94. package/dist/schema.d.ts.map +1 -1
  95. package/dist/schema.js +59 -30
  96. package/dist/schema.js.map +1 -1
  97. package/dist/scoped-stack/authority-snapshot.d.ts +37 -0
  98. package/dist/scoped-stack/authority-snapshot.d.ts.map +1 -0
  99. package/dist/scoped-stack/authority-snapshot.js +49 -0
  100. package/dist/scoped-stack/authority-snapshot.js.map +1 -0
  101. package/dist/scoped-stack/authority.d.ts +169 -0
  102. package/dist/scoped-stack/authority.d.ts.map +1 -0
  103. package/dist/scoped-stack/authority.js +408 -0
  104. package/dist/scoped-stack/authority.js.map +1 -0
  105. package/dist/scoped-stack/family-policy.d.ts +59 -0
  106. package/dist/scoped-stack/family-policy.d.ts.map +1 -0
  107. package/dist/scoped-stack/family-policy.js +68 -0
  108. package/dist/scoped-stack/family-policy.js.map +1 -0
  109. package/dist/scoped-stack/scoped-stack.d.ts +318 -0
  110. package/dist/scoped-stack/scoped-stack.d.ts.map +1 -0
  111. package/dist/scoped-stack/scoped-stack.js +695 -0
  112. package/dist/scoped-stack/scoped-stack.js.map +1 -0
  113. package/dist/scoped-stack/subscription.d.ts +36 -0
  114. package/dist/scoped-stack/subscription.d.ts.map +1 -0
  115. package/dist/scoped-stack/subscription.js +69 -0
  116. package/dist/scoped-stack/subscription.js.map +1 -0
  117. package/dist/stack/arguments.d.ts +27 -0
  118. package/dist/stack/arguments.d.ts.map +1 -0
  119. package/dist/stack/arguments.js +53 -0
  120. package/dist/stack/arguments.js.map +1 -0
  121. package/dist/stack/attachments.d.ts +24 -0
  122. package/dist/stack/attachments.d.ts.map +1 -0
  123. package/dist/stack/attachments.js +113 -0
  124. package/dist/stack/attachments.js.map +1 -0
  125. package/dist/{changes.d.ts → stack/changes.d.ts} +30 -72
  126. package/dist/stack/changes.d.ts.map +1 -0
  127. package/dist/{changes.js → stack/changes.js} +40 -74
  128. package/dist/stack/changes.js.map +1 -0
  129. package/dist/stack/client.d.ts +247 -0
  130. package/dist/stack/client.d.ts.map +1 -0
  131. package/dist/stack/client.js +9 -0
  132. package/dist/stack/client.js.map +1 -0
  133. package/dist/stack/identity-bindings.d.ts.map +1 -0
  134. package/dist/{identity-bindings.js → stack/identity-bindings.js} +5 -14
  135. package/dist/stack/identity-bindings.js.map +1 -0
  136. package/dist/stack/install-app.d.ts +22 -0
  137. package/dist/stack/install-app.d.ts.map +1 -0
  138. package/dist/stack/install-app.js +262 -0
  139. package/dist/stack/install-app.js.map +1 -0
  140. package/dist/stack/integrity.d.ts +94 -0
  141. package/dist/stack/integrity.d.ts.map +1 -0
  142. package/dist/stack/integrity.js +268 -0
  143. package/dist/stack/integrity.js.map +1 -0
  144. package/dist/{limits.d.ts → stack/limits.d.ts} +2 -5
  145. package/dist/stack/limits.d.ts.map +1 -0
  146. package/dist/{limits.js → stack/limits.js} +3 -6
  147. package/dist/stack/limits.js.map +1 -0
  148. package/dist/stack/migrations.d.ts +59 -0
  149. package/dist/stack/migrations.d.ts.map +1 -0
  150. package/dist/stack/migrations.js +141 -0
  151. package/dist/stack/migrations.js.map +1 -0
  152. package/dist/stack/reads.d.ts +69 -0
  153. package/dist/stack/reads.d.ts.map +1 -0
  154. package/dist/stack/reads.js +141 -0
  155. package/dist/stack/reads.js.map +1 -0
  156. package/dist/stack/record-id.d.ts +35 -0
  157. package/dist/stack/record-id.d.ts.map +1 -0
  158. package/dist/stack/record-id.js +82 -0
  159. package/dist/stack/record-id.js.map +1 -0
  160. package/dist/stack/stack.d.ts +444 -0
  161. package/dist/stack/stack.d.ts.map +1 -0
  162. package/dist/stack/stack.js +1339 -0
  163. package/dist/stack/stack.js.map +1 -0
  164. package/dist/stack/system-types.d.ts +16 -0
  165. package/dist/stack/system-types.d.ts.map +1 -0
  166. package/dist/stack/system-types.js +111 -0
  167. package/dist/stack/system-types.js.map +1 -0
  168. package/dist/stack/type-grants.d.ts +20 -0
  169. package/dist/stack/type-grants.d.ts.map +1 -0
  170. package/dist/stack/type-grants.js +69 -0
  171. package/dist/stack/type-grants.js.map +1 -0
  172. package/dist/stack/write-expectation.d.ts +79 -0
  173. package/dist/stack/write-expectation.d.ts.map +1 -0
  174. package/dist/stack/write-expectation.js +71 -0
  175. package/dist/stack/write-expectation.js.map +1 -0
  176. package/dist/stack/write-gate.d.ts +23 -0
  177. package/dist/stack/write-gate.d.ts.map +1 -0
  178. package/dist/stack/write-gate.js +17 -0
  179. package/dist/stack/write-gate.js.map +1 -0
  180. package/dist/testing.d.ts +44 -33
  181. package/dist/testing.d.ts.map +1 -1
  182. package/dist/testing.js +180 -176
  183. package/dist/testing.js.map +1 -1
  184. package/dist/type-handle.d.ts +67 -78
  185. package/dist/type-handle.d.ts.map +1 -1
  186. package/dist/type-handle.js +44 -111
  187. package/dist/type-handle.js.map +1 -1
  188. package/dist/types/adapter.d.ts +282 -0
  189. package/dist/types/adapter.d.ts.map +1 -0
  190. package/dist/types/adapter.js +5 -0
  191. package/dist/types/adapter.js.map +1 -0
  192. package/dist/types/associations.d.ts +140 -0
  193. package/dist/types/associations.d.ts.map +1 -0
  194. package/dist/types/associations.js +6 -0
  195. package/dist/types/associations.js.map +1 -0
  196. package/dist/types/capabilities.d.ts +89 -0
  197. package/dist/types/capabilities.d.ts.map +1 -0
  198. package/dist/types/capabilities.js +5 -0
  199. package/dist/types/capabilities.js.map +1 -0
  200. package/dist/types/events.d.ts +150 -0
  201. package/dist/types/events.d.ts.map +1 -0
  202. package/dist/types/events.js +5 -0
  203. package/dist/types/events.js.map +1 -0
  204. package/dist/types/ids.d.ts +43 -0
  205. package/dist/types/ids.d.ts.map +1 -0
  206. package/dist/types/ids.js +5 -0
  207. package/dist/types/ids.js.map +1 -0
  208. package/dist/types/index.d.ts +19 -0
  209. package/dist/types/index.d.ts.map +1 -0
  210. package/dist/types/index.js +19 -0
  211. package/dist/types/index.js.map +1 -0
  212. package/dist/types/journal.d.ts +47 -0
  213. package/dist/types/journal.d.ts.map +1 -0
  214. package/dist/types/journal.js +5 -0
  215. package/dist/types/journal.js.map +1 -0
  216. package/dist/types/query.d.ts +185 -0
  217. package/dist/types/query.d.ts.map +1 -0
  218. package/dist/types/query.js +10 -0
  219. package/dist/types/query.js.map +1 -0
  220. package/dist/types/records.d.ts +76 -0
  221. package/dist/types/records.d.ts.map +1 -0
  222. package/dist/types/records.js +5 -0
  223. package/dist/types/records.js.map +1 -0
  224. package/dist/types/schema.d.ts +74 -0
  225. package/dist/types/schema.d.ts.map +1 -0
  226. package/dist/types/schema.js +5 -0
  227. package/dist/types/schema.js.map +1 -0
  228. package/dist/types/system.d.ts +161 -0
  229. package/dist/types/system.d.ts.map +1 -0
  230. package/dist/types/system.js +32 -0
  231. package/dist/types/system.js.map +1 -0
  232. package/dist/types/tokens.d.ts +39 -0
  233. package/dist/types/tokens.d.ts.map +1 -0
  234. package/dist/types/tokens.js +5 -0
  235. package/dist/types/tokens.js.map +1 -0
  236. package/dist/validate.d.ts +31 -70
  237. package/dist/validate.d.ts.map +1 -1
  238. package/dist/validate.js +52 -92
  239. package/dist/validate.js.map +1 -1
  240. package/dist/{attachment-download.d.ts → wire/attachment-download.d.ts} +0 -57
  241. package/dist/wire/attachment-download.d.ts.map +1 -0
  242. package/dist/{attachment-download.js → wire/attachment-download.js} +0 -61
  243. package/dist/wire/attachment-download.js.map +1 -0
  244. package/dist/{auth.d.ts → wire/auth.d.ts} +5 -8
  245. package/dist/wire/auth.d.ts.map +1 -0
  246. package/dist/{auth.js → wire/auth.js} +5 -8
  247. package/dist/wire/auth.js.map +1 -0
  248. package/dist/{wire-body.d.ts → wire/body.d.ts} +35 -12
  249. package/dist/wire/body.d.ts.map +1 -0
  250. package/dist/{wire-body.js → wire/body.js} +74 -13
  251. package/dist/wire/body.js.map +1 -0
  252. package/dist/{wire-entry.d.ts → wire/index.d.ts} +12 -12
  253. package/dist/wire/index.d.ts.map +1 -0
  254. package/dist/{wire-entry.js → wire/index.js} +13 -17
  255. package/dist/wire/index.js.map +1 -0
  256. package/dist/wire/record.d.ts +31 -0
  257. package/dist/wire/record.d.ts.map +1 -0
  258. package/dist/{wire-record.js → wire/record.js} +7 -67
  259. package/dist/wire/record.js.map +1 -0
  260. package/dist/{wire-request.d.ts → wire/request.d.ts} +32 -49
  261. package/dist/wire/request.d.ts.map +1 -0
  262. package/dist/{wire-request.js → wire/request.js} +113 -83
  263. package/dist/wire/request.js.map +1 -0
  264. package/package.json +7 -7
  265. package/dist/adapter-entry.d.ts +0 -16
  266. package/dist/adapter-entry.d.ts.map +0 -1
  267. package/dist/adapter-entry.js +0 -14
  268. package/dist/adapter-entry.js.map +0 -1
  269. package/dist/attachment-download.d.ts.map +0 -1
  270. package/dist/attachment-download.js.map +0 -1
  271. package/dist/auth.d.ts.map +0 -1
  272. package/dist/auth.js.map +0 -1
  273. package/dist/changes.d.ts.map +0 -1
  274. package/dist/changes.js.map +0 -1
  275. package/dist/combine.d.ts.map +0 -1
  276. package/dist/combine.js.map +0 -1
  277. package/dist/did-entry.d.ts.map +0 -1
  278. package/dist/did-entry.js.map +0 -1
  279. package/dist/did.d.ts.map +0 -1
  280. package/dist/did.js.map +0 -1
  281. package/dist/identity-bindings.d.ts.map +0 -1
  282. package/dist/identity-bindings.js.map +0 -1
  283. package/dist/limits.d.ts.map +0 -1
  284. package/dist/limits.js.map +0 -1
  285. package/dist/record-id.d.ts +0 -70
  286. package/dist/record-id.d.ts.map +0 -1
  287. package/dist/record-id.js +0 -127
  288. package/dist/record-id.js.map +0 -1
  289. package/dist/scoped-stack.d.ts +0 -549
  290. package/dist/scoped-stack.d.ts.map +0 -1
  291. package/dist/scoped-stack.js +0 -1301
  292. package/dist/scoped-stack.js.map +0 -1
  293. package/dist/sort.d.ts.map +0 -1
  294. package/dist/sort.js.map +0 -1
  295. package/dist/stack-reads.d.ts +0 -38
  296. package/dist/stack-reads.d.ts.map +0 -1
  297. package/dist/stack-reads.js +0 -79
  298. package/dist/stack-reads.js.map +0 -1
  299. package/dist/stack.d.ts +0 -1032
  300. package/dist/stack.d.ts.map +0 -1
  301. package/dist/stack.js +0 -2337
  302. package/dist/stack.js.map +0 -1
  303. package/dist/types.d.ts +0 -1278
  304. package/dist/types.d.ts.map +0 -1
  305. package/dist/types.js +0 -51
  306. package/dist/types.js.map +0 -1
  307. package/dist/wire-body.d.ts.map +0 -1
  308. package/dist/wire-body.js.map +0 -1
  309. package/dist/wire-entry.d.ts.map +0 -1
  310. package/dist/wire-entry.js.map +0 -1
  311. package/dist/wire-record.d.ts +0 -50
  312. package/dist/wire-record.d.ts.map +0 -1
  313. package/dist/wire-record.js.map +0 -1
  314. package/dist/wire-request.d.ts.map +0 -1
  315. package/dist/wire-request.js.map +0 -1
  316. /package/dist/{did.d.ts → did/did.d.ts} +0 -0
  317. /package/dist/{identity-bindings.d.ts → stack/identity-bindings.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/stack/integrity.ts"],"names":[],"mappings":"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"}
@@ -13,11 +13,8 @@
13
13
  export declare function assertAttachmentSize(byteLength: number, attachmentBytes: number | null): void;
14
14
  /**
15
15
  * The content half of the same pre-check, on Stack.create() and
16
- * Stack.mutate(). Local adapters declare `limits.contentBytes: null` and skip
17
- * the serialization entirely; only a server declares a ceiling, and its
18
- * own request-size limit stays authoritative — this just spares an app the
19
- * round trip and gives it a typed failure instead of a 413 it has to
20
- * interpret. See docs/spec/wire-format.md § Request size limits.
16
+ * Stack.patchContent(). A `null` ceiling — every local adapter's — skips the
17
+ * serialization entirely.
21
18
  */
22
19
  export declare function assertContentSize(content: Record<string, unknown>, contentBytes: number | null, what: 'Content' | 'Patch'): void;
23
20
  //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/stack/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAM7F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,IAAI,EAAE,SAAS,GAAG,OAAO,GACxB,IAAI,CAQN"}
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * See docs/spec/wire-format.md § Request size limits.
11
11
  */
12
- import { StackPayloadTooLargeError } from './errors.js';
12
+ import { StackPayloadTooLargeError } from '../errors.js';
13
13
  /** Shared by Stack.putAttachment() and ScopedStack.putAttachment(). */
14
14
  export function assertAttachmentSize(byteLength, attachmentBytes) {
15
15
  if (attachmentBytes !== null && byteLength > attachmentBytes) {
@@ -18,11 +18,8 @@ export function assertAttachmentSize(byteLength, attachmentBytes) {
18
18
  }
19
19
  /**
20
20
  * The content half of the same pre-check, on Stack.create() and
21
- * Stack.mutate(). Local adapters declare `limits.contentBytes: null` and skip
22
- * the serialization entirely; only a server declares a ceiling, and its
23
- * own request-size limit stays authoritative — this just spares an app the
24
- * round trip and gives it a typed failure instead of a 413 it has to
25
- * interpret. See docs/spec/wire-format.md § Request size limits.
21
+ * Stack.patchContent(). A `null` ceiling — every local adapter's — skips the
22
+ * serialization entirely.
26
23
  */
27
24
  export function assertContentSize(content, contentBytes, what) {
28
25
  if (contentBytes === null)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/stack/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEzD,uEAAuE;AACvE,MAAM,UAAU,oBAAoB,CAAC,UAAkB,EAAE,eAA8B;IACrF,IAAI,eAAe,KAAK,IAAI,IAAI,UAAU,GAAG,eAAe,EAAE,CAAC;QAC7D,MAAM,IAAI,yBAAyB,CACjC,eAAe,UAAU,uBAAuB,eAAe,cAAc,CAC9E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgC,EAChC,YAA2B,EAC3B,IAAyB;IAEzB,IAAI,YAAY,KAAK,IAAI;QAAE,OAAO;IAClC,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5E,IAAI,UAAU,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,KAAK,UAAU,uBAAuB,YAAY,cAAc,CACxE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Migration registry
3
+ * -------------------------------------------------------
4
+ * The migrations a Stack was opened with, and what this app process
5
+ * understands of each type family. Answers two questions for the Stack:
6
+ * which chain carries a record from one TypeId to another (for
7
+ * migrateAll() and a collection's in-memory reads), and how a stored
8
+ * record reads at `presentAt: 'latest'` — never written back. See
9
+ * docs/spec/data-model.md § Type migrations.
10
+ */
11
+ import type { StackRecord, TypeId } from '../types/index.js';
12
+ import type { Migration } from '../type-handle.js';
13
+ import type { FieldOrigins } from '../migration-steps.js';
14
+ export declare class MigrationRegistry {
15
+ private readonly steps;
16
+ /**
17
+ * Highest version this instance has defineType()'d, per baseId — what
18
+ * this app process understands, as distinct from what exists in shared
19
+ * storage. Used to detect the stale-writer case in presentAtLatest().
20
+ */
21
+ private readonly maxDefinedVersion;
22
+ /**
23
+ * Refuses anything the walkers below could not follow. Each TypeId has at
24
+ * most one step out, so the graph is a set of chains, and a walk that
25
+ * comes back to a TypeId it already passed is a cycle.
26
+ */
27
+ constructor(migrations: readonly Migration[]);
28
+ /**
29
+ * Record that this instance has defined `version` of `baseId` — on the
30
+ * idempotent-no-op path too, since presentAtLatest()'s stale-writer
31
+ * detection depends on it.
32
+ */
33
+ noteDefined(baseId: string, version: number): void;
34
+ /**
35
+ * Find and compose a migration path from one TypeId to another.
36
+ * Returns null if no path exists.
37
+ */
38
+ path(fromId: TypeId, toId: TypeId): Migration['migrate'] | null;
39
+ /**
40
+ * What each of `toId`'s top-level fields is in terms of `fromId`'s,
41
+ * composed along the path between them. Null when there is no path, or
42
+ * when a step on it was not built by `migration()` and so declares
43
+ * nothing. See docs/spec/data-model.md § Content queries across versions.
44
+ */
45
+ origins(fromId: TypeId, toId: TypeId): FieldOrigins | null;
46
+ /**
47
+ * Find the latest registered version of a type family.
48
+ * Follows the migration chain from the given typeId to the end.
49
+ */
50
+ latest(fromId: TypeId): TypeId;
51
+ /**
52
+ * Apply the registered migration chain in memory, for presentAt:
53
+ * 'latest'. Never writes back. Throws StackMigrationError when the
54
+ * record's version can't be reconciled with what this instance has
55
+ * registered — the stale-writer case.
56
+ */
57
+ presentAtLatest(record: StackRecord): StackRecord;
58
+ }
59
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/stack/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAE/D;;;;OAIG;gBACS,UAAU,EAAE,SAAS,SAAS,EAAE;IAiC5C;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKlD;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI;IAgB/D;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAY1D;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ9B;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW;CA2BlD"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Migration registry
3
+ * -------------------------------------------------------
4
+ * The migrations a Stack was opened with, and what this app process
5
+ * understands of each type family. Answers two questions for the Stack:
6
+ * which chain carries a record from one TypeId to another (for
7
+ * migrateAll() and a collection's in-memory reads), and how a stored
8
+ * record reads at `presentAt: 'latest'` — never written back. See
9
+ * docs/spec/data-model.md § Type migrations.
10
+ */
11
+ import { parseTypeId } from '../schema.js';
12
+ import { StackMigrationError } from '../errors.js';
13
+ import { composeOrigins, originsOf } from '../migration-steps.js';
14
+ export class MigrationRegistry {
15
+ steps = new Map();
16
+ /**
17
+ * Highest version this instance has defineType()'d, per baseId — what
18
+ * this app process understands, as distinct from what exists in shared
19
+ * storage. Used to detect the stale-writer case in presentAtLatest().
20
+ */
21
+ maxDefinedVersion = new Map();
22
+ /**
23
+ * Refuses anything the walkers below could not follow. Each TypeId has at
24
+ * most one step out, so the graph is a set of chains, and a walk that
25
+ * comes back to a TypeId it already passed is a cycle.
26
+ */
27
+ constructor(migrations) {
28
+ for (const m of migrations) {
29
+ const from = parseTypeId(m.from);
30
+ const to = parseTypeId(m.to);
31
+ if (!from || !to) {
32
+ throw new StackMigrationError(`Migration "${m.from}" → "${m.to}" must name two versioned TypeIds.`);
33
+ }
34
+ if (from.baseId === to.baseId && to.version <= from.version) {
35
+ throw new StackMigrationError(`Migration "${m.from}" → "${m.to}" must go to a later version of its family.`);
36
+ }
37
+ if (this.steps.has(m.from)) {
38
+ throw new StackMigrationError(`More than one migration from "${m.from}" was passed.`);
39
+ }
40
+ this.steps.set(m.from, m);
41
+ }
42
+ const acyclic = new Set();
43
+ for (const start of this.steps.keys()) {
44
+ const walked = new Set();
45
+ for (let at = start; at && !acyclic.has(at);) {
46
+ if (walked.has(at)) {
47
+ throw new StackMigrationError(`The migrations passed form a cycle through "${at}".`);
48
+ }
49
+ walked.add(at);
50
+ at = this.steps.get(at)?.to;
51
+ }
52
+ for (const id of walked)
53
+ acyclic.add(id);
54
+ }
55
+ }
56
+ /**
57
+ * Record that this instance has defined `version` of `baseId` — on the
58
+ * idempotent-no-op path too, since presentAtLatest()'s stale-writer
59
+ * detection depends on it.
60
+ */
61
+ noteDefined(baseId, version) {
62
+ const priorMax = this.maxDefinedVersion.get(baseId) ?? 0;
63
+ if (version > priorMax)
64
+ this.maxDefinedVersion.set(baseId, version);
65
+ }
66
+ /**
67
+ * Find and compose a migration path from one TypeId to another.
68
+ * Returns null if no path exists.
69
+ */
70
+ path(fromId, toId) {
71
+ if (fromId === toId)
72
+ return (content) => content;
73
+ const steps = [];
74
+ let current = fromId;
75
+ while (current !== toId) {
76
+ const step = this.steps.get(current);
77
+ if (!step)
78
+ return null;
79
+ steps.push(step);
80
+ current = step.to;
81
+ }
82
+ return (content) => steps.reduce((c, step) => step.migrate(c), content);
83
+ }
84
+ /**
85
+ * What each of `toId`'s top-level fields is in terms of `fromId`'s,
86
+ * composed along the path between them. Null when there is no path, or
87
+ * when a step on it was not built by `migration()` and so declares
88
+ * nothing. See docs/spec/data-model.md § Content queries across versions.
89
+ */
90
+ origins(fromId, toId) {
91
+ let composed = null;
92
+ for (let current = fromId; current !== toId;) {
93
+ const step = this.steps.get(current);
94
+ const origins = step && originsOf(step);
95
+ if (!origins)
96
+ return null;
97
+ composed = composed ? composeOrigins(composed, origins) : origins;
98
+ current = step.to;
99
+ }
100
+ return composed;
101
+ }
102
+ /**
103
+ * Find the latest registered version of a type family.
104
+ * Follows the migration chain from the given typeId to the end.
105
+ */
106
+ latest(fromId) {
107
+ let current = fromId;
108
+ for (let step = this.steps.get(current); step; step = this.steps.get(current)) {
109
+ current = step.to;
110
+ }
111
+ return current;
112
+ }
113
+ /**
114
+ * Apply the registered migration chain in memory, for presentAt:
115
+ * 'latest'. Never writes back. Throws StackMigrationError when the
116
+ * record's version can't be reconciled with what this instance has
117
+ * registered — the stale-writer case.
118
+ */
119
+ presentAtLatest(record) {
120
+ const latestId = this.latest(record.typeId);
121
+ if (latestId !== record.typeId) {
122
+ // latest() found this by walking the same migration graph path()
123
+ // walks, from the same starting point, so a path is always
124
+ // resolvable here.
125
+ const migrateFn = this.path(record.typeId, latestId);
126
+ return { ...record, typeId: latestId, content: migrateFn(record.content) };
127
+ }
128
+ const parsed = parseTypeId(record.typeId);
129
+ const knownMax = parsed ? this.maxDefinedVersion.get(parsed.baseId) : undefined;
130
+ if (parsed && knownMax !== undefined && parsed.version !== knownMax) {
131
+ const direction = parsed.version > knownMax
132
+ ? `the record is newer than this app instance understands — update the app, or pass it the missing migrations`
133
+ : `no migration passed to Stack.open() bridges the gap`;
134
+ throw new StackMigrationError(`Record "${record.id}" is at "${record.typeId}", but this app instance has defined ` +
135
+ `up to "${parsed.baseId}@${knownMax}": ${direction}. Omit presentAt: "latest" to ` +
136
+ `read the record as stored.`);
137
+ }
138
+ return record;
139
+ }
140
+ }
141
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/stack/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Canned reads over a stack
3
+ * -------------------------------------------------------
4
+ * The internal call sites that need every match rather than a page —
5
+ * grant checks, attachment cleanup, DID resolution — expressed once. Most
6
+ * take the query function to run against, so the same read serves an
7
+ * unscoped `Stack` and a permission-filtered `ScopedStack` without either
8
+ * knowing which it got; the `_app` and `_install` reads must see past
9
+ * deletion and listing, so they take the unscoped `Stack` itself. Also the
10
+ * page-size bounds both classes' query() applies.
11
+ *
12
+ * None of these is a public API.
13
+ */
14
+ import type { Stack } from './stack.js';
15
+ import type { EntityId, GrantContent, GroupRole, InstallContent, QueryResult, RecordId, StackQuery, StackRecord } from '../types/index.js';
16
+ /**
17
+ * Walks `cursor` to exhaustion for the internal call sites that need every
18
+ * match (grant checks, attachment cleanup) — query() itself always
19
+ * paginates. Throws StackBadRequestError past `max` rather than silently
20
+ * truncating a runaway scan. Not a public API.
21
+ */
22
+ export declare function queryAllPages(run: (query: StackQuery) => Promise<QueryResult>, query: StackQuery, max?: number): Promise<StackRecord[]>;
23
+ /**
24
+ * Cursor-walks `run(query)` looking for the first record matching
25
+ * `predicate`, short-circuiting on a match. Same bounded-scan discipline
26
+ * as queryAllPages(): a match past page one is still found, and a
27
+ * non-terminating scan throws StackBadRequestError.
28
+ */
29
+ export declare function findFirstMatch(run: (query: StackQuery) => Promise<QueryResult>, query: StackQuery, predicate: (record: StackRecord) => boolean | Promise<boolean>, max?: number): Promise<StackRecord | undefined>;
30
+ /**
31
+ * Shared implementation behind Stack.getEntityByDid() and
32
+ * ScopedStack.getEntityByDid() — see docs/spec/identity.md § DID bindings
33
+ * for the matching rules. `includeUnlisted` is a parameter rather than
34
+ * hardcoded, so a caller not permitted to set it can omit it instead of
35
+ * having query() throw.
36
+ */
37
+ export declare function lookupEntityByDid(run: (query: StackQuery) => Promise<QueryResult>, did: EntityId, canFilterContent: boolean, includeUnlisted: boolean): Promise<StackRecord | null>;
38
+ /**
39
+ * The `_app` card claiming `did`, deleted and unlisted included — the
40
+ * binding rules make it single-valued. Takes the unscoped Stack, since no
41
+ * scoped view may read past deletion and listing for everyone.
42
+ * See docs/spec/identity.md § DID bindings.
43
+ */
44
+ export declare function findAppCardByDid(stack: Stack, did: EntityId): Promise<StackRecord | undefined>;
45
+ /**
46
+ * Every `_install` Record, deleted and unlisted included — a deleted
47
+ * install keeps its claims. Takes the unscoped Stack, as findAppCardByDid().
48
+ */
49
+ export declare function loadInstallRecords(stack: Stack): Promise<(StackRecord & {
50
+ content: InstallContent;
51
+ })[]>;
52
+ /**
53
+ * Every `_grant` Record, cursor-walked through an unscoped query: a grant
54
+ * decides who may read, so it can't sit behind a read check. Unlisted ones
55
+ * count, as listing decides nothing about what a grant confers; deleted
56
+ * ones don't, as soft-deleting is revoking. See docs/spec/unlisted.md.
57
+ */
58
+ export declare function loadGrantRecords(run: (query: StackQuery) => Promise<QueryResult>): Promise<(StackRecord & {
59
+ content: GrantContent;
60
+ })[]>;
61
+ /**
62
+ * The role `entityId` holds on every roster that holds it, keyed by group
63
+ * id — the one reading of which rosters reach an entity. A roster is a
64
+ * live `_group`'s relationships: a Record outside the family or a deleted
65
+ * Group reaches nobody, and unlisted ones count, as for grants above. See
66
+ * docs/spec/access-control.md § Record-level permissions.
67
+ */
68
+ export declare function loadRosterRoles(run: (query: StackQuery) => Promise<QueryResult>, entityId: EntityId): Promise<Map<RecordId, GroupRole>>;
69
+ //# sourceMappingURL=reads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../../src/stack/reads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAGV,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,cAAc,EACd,WAAW,EACX,QAAQ,EACR,UAAU,EACV,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,EAChD,KAAK,EAAE,UAAU,EACjB,GAAG,SAAgB,GAClB,OAAO,CAAC,WAAW,EAAE,CAAC,CAcxB;AAKD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,EAChD,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAC9D,GAAG,SAAgB,GAClB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAiBlC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,EAChD,GAAG,EAAE,QAAQ,EACb,gBAAgB,EAAE,OAAO,EACzB,eAAe,EAAE,OAAO,GACvB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAc7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAa9F;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,CAAC,WAAW,GAAG;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,EAAE,CAAC,CAKxD;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,GAC/C,OAAO,CAAC,CAAC,WAAW,GAAG;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,EAAE,CAAC,CAKtD;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,CAAC,EAChD,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAcnC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Canned reads over a stack
3
+ * -------------------------------------------------------
4
+ * The internal call sites that need every match rather than a page —
5
+ * grant checks, attachment cleanup, DID resolution — expressed once. Most
6
+ * take the query function to run against, so the same read serves an
7
+ * unscoped `Stack` and a permission-filtered `ScopedStack` without either
8
+ * knowing which it got; the `_app` and `_install` reads must see past
9
+ * deletion and listing, so they take the unscoped `Stack` itself. Also the
10
+ * page-size bounds both classes' query() applies.
11
+ *
12
+ * None of these is a public API.
13
+ */
14
+ import { groupRoleFromAssociations } from '../access.js';
15
+ import { StackBadRequestError } from '../errors.js';
16
+ import { filtersContent } from '../query-validation.js';
17
+ import { SYSTEM_TYPES } from '../types/index.js';
18
+ /**
19
+ * Walks `cursor` to exhaustion for the internal call sites that need every
20
+ * match (grant checks, attachment cleanup) — query() itself always
21
+ * paginates. Throws StackBadRequestError past `max` rather than silently
22
+ * truncating a runaway scan. Not a public API.
23
+ */
24
+ export async function queryAllPages(run, query, max = QUERY_ALL_MAX) {
25
+ const records = [];
26
+ let cursor = query.cursor;
27
+ do {
28
+ const page = await run({ ...query, cursor });
29
+ records.push(...page.records);
30
+ if (records.length > max) {
31
+ throw new StackBadRequestError(`queryAllPages: exceeded max of ${max} records without exhausting the cursor`);
32
+ }
33
+ cursor = page.cursor ?? undefined;
34
+ } while (cursor);
35
+ return records;
36
+ }
37
+ /** Safety cap for queryAllPages() — generous for personal-stack scale. */
38
+ const QUERY_ALL_MAX = 10_000;
39
+ /**
40
+ * Cursor-walks `run(query)` looking for the first record matching
41
+ * `predicate`, short-circuiting on a match. Same bounded-scan discipline
42
+ * as queryAllPages(): a match past page one is still found, and a
43
+ * non-terminating scan throws StackBadRequestError.
44
+ */
45
+ export async function findFirstMatch(run, query, predicate, max = QUERY_ALL_MAX) {
46
+ let cursor = query.cursor;
47
+ let totalFetched = 0;
48
+ do {
49
+ const page = await run({ ...query, cursor });
50
+ totalFetched += page.records.length;
51
+ if (totalFetched > max) {
52
+ throw new StackBadRequestError(`findFirstMatch: exceeded max of ${max} records without exhausting the cursor`);
53
+ }
54
+ for (const record of page.records) {
55
+ if (await predicate(record))
56
+ return record;
57
+ }
58
+ cursor = page.cursor ?? undefined;
59
+ } while (cursor);
60
+ return undefined;
61
+ }
62
+ /**
63
+ * Shared implementation behind Stack.getEntityByDid() and
64
+ * ScopedStack.getEntityByDid() — see docs/spec/identity.md § DID bindings
65
+ * for the matching rules. `includeUnlisted` is a parameter rather than
66
+ * hardcoded, so a caller not permitted to set it can omit it instead of
67
+ * having query() throw.
68
+ */
69
+ export async function lookupEntityByDid(run, did, canFilterContent, includeUnlisted) {
70
+ const record = await findFirstMatch(run, {
71
+ filter: {
72
+ baseId: SYSTEM_TYPES.ENTITY,
73
+ includeDeleted: true,
74
+ ...(includeUnlisted && { includeUnlisted: true }),
75
+ ...(canFilterContent && { content: { did } }),
76
+ },
77
+ }, (r) => r.content.did === did);
78
+ return record ?? null;
79
+ }
80
+ /**
81
+ * The `_app` card claiming `did`, deleted and unlisted included — the
82
+ * binding rules make it single-valued. Takes the unscoped Stack, since no
83
+ * scoped view may read past deletion and listing for everyone.
84
+ * See docs/spec/identity.md § DID bindings.
85
+ */
86
+ export function findAppCardByDid(stack, did) {
87
+ return findFirstMatch((q) => stack.query(q), {
88
+ filter: {
89
+ baseId: SYSTEM_TYPES.APP,
90
+ includeDeleted: true,
91
+ includeUnlisted: true,
92
+ ...(filtersContent(stack.capabilities) && { content: { did } }),
93
+ },
94
+ }, (r) => r.content.did === did);
95
+ }
96
+ /**
97
+ * Every `_install` Record, deleted and unlisted included — a deleted
98
+ * install keeps its claims. Takes the unscoped Stack, as findAppCardByDid().
99
+ */
100
+ export async function loadInstallRecords(stack) {
101
+ const records = await queryAllPages((q) => stack.query(q), {
102
+ filter: { baseId: SYSTEM_TYPES.INSTALL, includeDeleted: true, includeUnlisted: true },
103
+ });
104
+ return records;
105
+ }
106
+ /**
107
+ * Every `_grant` Record, cursor-walked through an unscoped query: a grant
108
+ * decides who may read, so it can't sit behind a read check. Unlisted ones
109
+ * count, as listing decides nothing about what a grant confers; deleted
110
+ * ones don't, as soft-deleting is revoking. See docs/spec/unlisted.md.
111
+ */
112
+ export async function loadGrantRecords(run) {
113
+ const records = await queryAllPages(run, {
114
+ filter: { typeId: `${SYSTEM_TYPES.GRANT}@1`, includeUnlisted: true },
115
+ });
116
+ return records;
117
+ }
118
+ /**
119
+ * The role `entityId` holds on every roster that holds it, keyed by group
120
+ * id — the one reading of which rosters reach an entity. A roster is a
121
+ * live `_group`'s relationships: a Record outside the family or a deleted
122
+ * Group reaches nobody, and unlisted ones count, as for grants above. See
123
+ * docs/spec/access-control.md § Record-level permissions.
124
+ */
125
+ export async function loadRosterRoles(run, entityId) {
126
+ const groups = await queryAllPages(run, {
127
+ filter: {
128
+ baseId: SYSTEM_TYPES.GROUP,
129
+ relatedTo: { target: { kind: 'entity', entityId } },
130
+ includeUnlisted: true,
131
+ },
132
+ });
133
+ const roles = new Map();
134
+ for (const group of groups) {
135
+ const role = groupRoleFromAssociations(group.associations, entityId);
136
+ if (role)
137
+ roles.set(group.id, role);
138
+ }
139
+ return roles;
140
+ }
141
+ //# sourceMappingURL=reads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reads.js","sourceRoot":"","sources":["../../src/stack/reads.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Record ID and clock-field validation
3
+ * -------------------------------------------------------
4
+ * The rules a caller-supplied `id`, `parentId`, `createdAt` or `updatedAt`
5
+ * is held to before any of them reaches storage. A client may mint its own
6
+ * id and backdate a record's clock, so both are untrusted input here even
7
+ * when the types say otherwise.
8
+ *
9
+ * See docs/spec/data-model.md § Record IDs.
10
+ */
11
+ import type { ValidationError } from '../validate.js';
12
+ export declare const DEFAULT_ID_TIMESTAMP_SKEW_MS: number;
13
+ /**
14
+ * Format and reserved-prefix checks for a caller-supplied id, reported
15
+ * under `field` — `parentId` when the id names a destination rather than
16
+ * the record being written. The prefix is asked first so "_config" gets a
17
+ * specific refusal. StackBadRequestError, not StackValidationError: a
18
+ * malformed id never reaches schema validation.
19
+ */
20
+ export declare function validateRecordId(id: string, field?: string): void;
21
+ /**
22
+ * Validity and range check for a backdated `createdAt`/`updatedAt`. An
23
+ * Invalid Date would switch the ordering and skew checks off rather than
24
+ * fail them, and one outside an id's encodable range has no id to agree
25
+ * with. See docs/spec/data-model.md § Backdating on import.
26
+ */
27
+ export declare function validateClockField(value: Date | undefined, path: string): ValidationError[];
28
+ /**
29
+ * Whether an id's embedded timestamp is within `skewMs` of `reference`:
30
+ * the current time for a live scoped create, where it stops a grantee
31
+ * forging a sort position, or an explicit `createdAt`, which the id must
32
+ * agree with. Pass null to disable. See docs/spec/data-model.md § Record IDs.
33
+ */
34
+ export declare function validateIdTimestampSkew(id: string, toleranceMs: number | null, referenceMs: number, referenceLabel: string): void;
35
+ //# sourceMappingURL=record-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-id.d.ts","sourceRoot":"","sources":["../../src/stack/record-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAOtD,eAAO,MAAM,4BAA4B,QAAsB,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAO,GAAG,IAAI,CAW/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAuB3F;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,IAAI,CAcN"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Record ID and clock-field validation
3
+ * -------------------------------------------------------
4
+ * The rules a caller-supplied `id`, `parentId`, `createdAt` or `updatedAt`
5
+ * is held to before any of them reaches storage. A client may mint its own
6
+ * id and backdate a record's clock, so both are untrusted input here even
7
+ * when the types say otherwise.
8
+ *
9
+ * See docs/spec/data-model.md § Record IDs.
10
+ */
11
+ import { isValidIdFormat, idTimestamp, MAX_ID_TIMESTAMP } from '../id.js';
12
+ import { ARGUMENTS_INVALID, StackBadRequestError, StackValidationError } from '../errors.js';
13
+ // -------------------------------------------------------
14
+ // Record ID validation
15
+ // -------------------------------------------------------
16
+ const RESERVED_ID_PREFIX = '_';
17
+ export const DEFAULT_ID_TIMESTAMP_SKEW_MS = 24 * 60 * 60 * 1000;
18
+ /**
19
+ * Format and reserved-prefix checks for a caller-supplied id, reported
20
+ * under `field` — `parentId` when the id names a destination rather than
21
+ * the record being written. The prefix is asked first so "_config" gets a
22
+ * specific refusal. StackBadRequestError, not StackValidationError: a
23
+ * malformed id never reaches schema validation.
24
+ */
25
+ export function validateRecordId(id, field = 'ID') {
26
+ if (id.startsWith(RESERVED_ID_PREFIX)) {
27
+ throw new StackBadRequestError(`Invalid ${field} "${id}": uses the reserved "${RESERVED_ID_PREFIX}" prefix.`);
28
+ }
29
+ if (!isValidIdFormat(id)) {
30
+ throw new StackBadRequestError(`Invalid ${field} "${id}": expected 12 lowercase Crockford base-32 characters.`);
31
+ }
32
+ }
33
+ /**
34
+ * Validity and range check for a backdated `createdAt`/`updatedAt`. An
35
+ * Invalid Date would switch the ordering and skew checks off rather than
36
+ * fail them, and one outside an id's encodable range has no id to agree
37
+ * with. See docs/spec/data-model.md § Backdating on import.
38
+ */
39
+ export function validateClockField(value, path) {
40
+ if (value === undefined)
41
+ return [];
42
+ // Reachable from the wire, where JSON has no Date: a forwarded request
43
+ // body hands over an ISO string, which must be a 400 naming the field
44
+ // rather than a TypeError from the getTime() below.
45
+ if (!(value instanceof Date)) {
46
+ return [{ path, message: `${path} must be a Date.` }];
47
+ }
48
+ const ms = value.getTime();
49
+ if (Number.isNaN(ms)) {
50
+ return [{ path, message: `${path} is not a valid Date.` }];
51
+ }
52
+ if (ms < 0 || ms > MAX_ID_TIMESTAMP) {
53
+ return [
54
+ {
55
+ path,
56
+ message: `${path} is outside the representable range ` +
57
+ `(1970-01-01T00:00:00.000Z…${new Date(MAX_ID_TIMESTAMP).toISOString()}).`,
58
+ },
59
+ ];
60
+ }
61
+ return [];
62
+ }
63
+ /**
64
+ * Whether an id's embedded timestamp is within `skewMs` of `reference`:
65
+ * the current time for a live scoped create, where it stops a grantee
66
+ * forging a sort position, or an explicit `createdAt`, which the id must
67
+ * agree with. Pass null to disable. See docs/spec/data-model.md § Record IDs.
68
+ */
69
+ export function validateIdTimestampSkew(id, toleranceMs, referenceMs, referenceLabel) {
70
+ if (toleranceMs === null)
71
+ return;
72
+ const skew = Math.abs(referenceMs - idTimestamp(id));
73
+ if (skew > toleranceMs) {
74
+ throw new StackValidationError([
75
+ {
76
+ path: 'id',
77
+ message: `ID "${id}" timestamp disagrees with ${referenceLabel} by more than the allowed clock-skew tolerance (${toleranceMs}ms).`,
78
+ },
79
+ ], ARGUMENTS_INVALID);
80
+ }
81
+ }
82
+ //# sourceMappingURL=record-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-id.js","sourceRoot":"","sources":["../../src/stack/record-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG7F,0DAA0D;AAC1D,uBAAuB;AACvB,0DAA0D;AAE1D,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAU,EAAE,KAAK,GAAG,IAAI;IACvD,IAAI,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,oBAAoB,CAC5B,WAAW,KAAK,KAAK,EAAE,yBAAyB,kBAAkB,WAAW,CAC9E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,oBAAoB,CAC5B,WAAW,KAAK,KAAK,EAAE,wDAAwD,CAChF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAuB,EAAE,IAAY;IACtE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,uEAAuE;IACvE,sEAAsE;IACtE,oDAAoD;IACpD,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,kBAAkB,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,uBAAuB,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,gBAAgB,EAAE,CAAC;QACpC,OAAO;YACL;gBACE,IAAI;gBACJ,OAAO,EACL,GAAG,IAAI,sCAAsC;oBAC7C,6BAA6B,IAAI,IAAI,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,IAAI;aAC5E;SACF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,EAAU,EACV,WAA0B,EAC1B,WAAmB,EACnB,cAAsB;IAEtB,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,IAAI,GAAG,WAAW,EAAE,CAAC;QACvB,MAAM,IAAI,oBAAoB,CAC5B;YACE;gBACE,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,OAAO,EAAE,8BAA8B,cAAc,mDAAmD,WAAW,MAAM;aACnI;SACF,EACD,iBAAiB,CAClB,CAAC;IACJ,CAAC;AACH,CAAC"}