@powerhousedao/shared 6.2.2-dev.9 → 6.2.2-staging.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 (227) hide show
  1. package/dist/clis/args/access-token--9H57y8J.d.mts +18 -0
  2. package/dist/clis/args/access-token--9H57y8J.d.mts.map +1 -0
  3. package/dist/clis/args/access-token-To5LaIfL.mjs +22 -0
  4. package/dist/clis/args/access-token-To5LaIfL.mjs.map +1 -0
  5. package/dist/clis/args/access-token.d.mts +2 -18
  6. package/dist/clis/args/access-token.mjs +1 -21
  7. package/dist/clis/args/{common-dbsvksvf.mjs → common-CcYbXrBx.mjs} +7 -2
  8. package/dist/clis/args/common-CcYbXrBx.mjs.map +1 -0
  9. package/dist/clis/args/{common-Cr8LZG55.d.mts → common-Dsf1vpHV.d.mts} +7 -4
  10. package/dist/clis/args/{common-Cr8LZG55.d.mts.map → common-Dsf1vpHV.d.mts.map} +1 -1
  11. package/dist/clis/args/common.d.mts +2 -2
  12. package/dist/clis/args/common.mjs +2 -2
  13. package/dist/clis/args/connect-BVVvCmL9.mjs +198 -0
  14. package/dist/clis/args/connect-BVVvCmL9.mjs.map +1 -0
  15. package/dist/clis/args/connect-DetTnI8g.d.mts +443 -0
  16. package/dist/clis/args/connect-DetTnI8g.d.mts.map +1 -0
  17. package/dist/clis/args/connect.d.mts +2 -434
  18. package/dist/clis/args/connect.mjs +1 -196
  19. package/dist/clis/args/{generate-Cs5okckF.mjs → generate-CA916Fvj.mjs} +2 -2
  20. package/dist/clis/args/{generate-Cs5okckF.mjs.map → generate-CA916Fvj.mjs.map} +1 -1
  21. package/dist/clis/args/generate-DnV-bfXt.d.mts +87 -0
  22. package/dist/clis/args/generate-DnV-bfXt.d.mts.map +1 -0
  23. package/dist/clis/args/generate.d.mts +2 -87
  24. package/dist/clis/args/generate.mjs +1 -1
  25. package/dist/clis/args/{help-BkF9Cxud.mjs → help-Bqbgbalu.mjs} +15 -15
  26. package/dist/clis/args/{help-BkF9Cxud.mjs.map → help-Bqbgbalu.mjs.map} +1 -1
  27. package/dist/clis/args/{help-CYjFrzIJ.d.mts → help-CjAsudUn.d.mts} +1 -1
  28. package/dist/clis/args/{help-CYjFrzIJ.d.mts.map → help-CjAsudUn.d.mts.map} +1 -1
  29. package/dist/clis/args/help.d.mts +1 -1
  30. package/dist/clis/args/help.mjs +1 -13
  31. package/dist/clis/args/index.d.mts +19 -19
  32. package/dist/clis/args/index.mjs +19 -19
  33. package/dist/clis/args/init-CUXyfquF.d.mts +55 -0
  34. package/dist/clis/args/init-CUXyfquF.d.mts.map +1 -0
  35. package/dist/clis/args/init-rz9Ei7nq.mjs +67 -0
  36. package/dist/clis/args/init-rz9Ei7nq.mjs.map +1 -0
  37. package/dist/clis/args/init.d.mts +2 -55
  38. package/dist/clis/args/init.mjs +1 -66
  39. package/dist/clis/args/inspect-DtZeoA5c.d.mts +15 -0
  40. package/dist/clis/args/inspect-DtZeoA5c.d.mts.map +1 -0
  41. package/dist/clis/args/inspect-tckH8mSw.mjs +15 -0
  42. package/dist/clis/args/inspect-tckH8mSw.mjs.map +1 -0
  43. package/dist/clis/args/inspect.d.mts +2 -15
  44. package/dist/clis/args/inspect.mjs +1 -14
  45. package/dist/clis/args/install-CkP8zcHb.d.mts +40 -0
  46. package/dist/clis/args/install-CkP8zcHb.d.mts.map +1 -0
  47. package/dist/clis/args/install-Sz2DlCHh.mjs +32 -0
  48. package/dist/clis/args/install-Sz2DlCHh.mjs.map +1 -0
  49. package/dist/clis/args/install.d.mts +2 -40
  50. package/dist/clis/args/install.mjs +1 -31
  51. package/dist/clis/args/list-BGf8s_gj.d.mts +12 -0
  52. package/dist/clis/args/list-BGf8s_gj.d.mts.map +1 -0
  53. package/dist/clis/args/list-DM2d6f1m.mjs +7 -0
  54. package/dist/clis/args/list-DM2d6f1m.mjs.map +1 -0
  55. package/dist/clis/args/list.d.mts +2 -12
  56. package/dist/clis/args/list.mjs +1 -6
  57. package/dist/clis/args/login-DNsHwvqk.d.mts +27 -0
  58. package/dist/clis/args/login-DNsHwvqk.d.mts.map +1 -0
  59. package/dist/clis/args/login-DiKT5Jfu.mjs +40 -0
  60. package/dist/clis/args/login-DiKT5Jfu.mjs.map +1 -0
  61. package/dist/clis/args/login.d.mts +2 -27
  62. package/dist/clis/args/login.mjs +1 -39
  63. package/dist/clis/args/magic-string.es-h_0HDQBQ.mjs +1013 -0
  64. package/dist/clis/args/magic-string.es-h_0HDQBQ.mjs.map +1 -0
  65. package/dist/clis/args/migrate-CG_gWc4k.mjs +29 -0
  66. package/dist/clis/args/migrate-CG_gWc4k.mjs.map +1 -0
  67. package/dist/clis/args/migrate-sixkWhxm.d.mts +21 -0
  68. package/dist/clis/args/migrate-sixkWhxm.d.mts.map +1 -0
  69. package/dist/clis/args/migrate.d.mts +2 -21
  70. package/dist/clis/args/migrate.mjs +1 -28
  71. package/dist/clis/args/publish-DDZYsUfV.mjs +19 -0
  72. package/dist/clis/args/publish-DDZYsUfV.mjs.map +1 -0
  73. package/dist/clis/args/publish-Dqe5DUst.d.mts +18 -0
  74. package/dist/clis/args/publish-Dqe5DUst.d.mts.map +1 -0
  75. package/dist/clis/args/publish.d.mts +2 -18
  76. package/dist/clis/args/publish.mjs +1 -18
  77. package/dist/clis/args/registry-C_OVFQmI.mjs +23 -0
  78. package/dist/clis/args/registry-C_OVFQmI.mjs.map +1 -0
  79. package/dist/clis/args/registry-C_RfTsKB.d.mts +19 -0
  80. package/dist/clis/args/registry-C_RfTsKB.d.mts.map +1 -0
  81. package/dist/clis/args/registry.d.mts +2 -19
  82. package/dist/clis/args/registry.mjs +1 -22
  83. package/dist/clis/args/service-CHOOr0Gg.mjs +11 -0
  84. package/dist/clis/args/service-CHOOr0Gg.mjs.map +1 -0
  85. package/dist/clis/args/{service-C88bN_g_.d.mts → service-DhIkf8-O.d.mts} +1 -1
  86. package/dist/clis/args/{service-C88bN_g_.d.mts.map → service-DhIkf8-O.d.mts.map} +1 -1
  87. package/dist/clis/args/service.d.mts +1 -1
  88. package/dist/clis/args/service.mjs +1 -10
  89. package/dist/clis/args/switchboard-BlPaq2at.d.mts +72 -0
  90. package/dist/clis/args/switchboard-BlPaq2at.d.mts.map +1 -0
  91. package/dist/clis/args/switchboard-Dsp7nosi.mjs +85 -0
  92. package/dist/clis/args/switchboard-Dsp7nosi.mjs.map +1 -0
  93. package/dist/clis/args/switchboard.d.mts +2 -72
  94. package/dist/clis/args/switchboard.mjs +1 -84
  95. package/dist/clis/args/uninstall-BpA3YYbw.d.mts +31 -0
  96. package/dist/clis/args/uninstall-BpA3YYbw.d.mts.map +1 -0
  97. package/dist/clis/args/uninstall-CTwTX0u_.mjs +16 -0
  98. package/dist/clis/args/uninstall-CTwTX0u_.mjs.map +1 -0
  99. package/dist/clis/args/uninstall.d.mts +2 -31
  100. package/dist/clis/args/uninstall.mjs +1 -15
  101. package/dist/clis/args/unpublish-BPMkGEg5.mjs +30 -0
  102. package/dist/clis/args/unpublish-BPMkGEg5.mjs.map +1 -0
  103. package/dist/clis/args/unpublish-CvwaIimG.d.mts +24 -0
  104. package/dist/clis/args/unpublish-CvwaIimG.d.mts.map +1 -0
  105. package/dist/clis/args/unpublish.d.mts +2 -24
  106. package/dist/clis/args/unpublish.mjs +1 -29
  107. package/dist/clis/args/vetra-DLQ6lhLl.d.mts +113 -0
  108. package/dist/clis/args/vetra-DLQ6lhLl.d.mts.map +1 -0
  109. package/dist/clis/args/vetra-b4KUu1Ax.mjs +126 -0
  110. package/dist/clis/args/vetra-b4KUu1Ax.mjs.map +1 -0
  111. package/dist/clis/args/vetra-ports.test.d.mts +1 -0
  112. package/dist/clis/args/vetra-ports.test.mjs +13249 -0
  113. package/dist/clis/args/vetra-ports.test.mjs.map +1 -0
  114. package/dist/clis/args/vetra.d.mts +2 -102
  115. package/dist/clis/args/vetra.mjs +2 -75
  116. package/dist/clis/build-config.d.mts +1 -1
  117. package/dist/clis/build-config.d.mts.map +1 -1
  118. package/dist/clis/constants.d.mts +199 -55
  119. package/dist/clis/constants.d.mts.map +1 -1
  120. package/dist/clis/constants.mjs +12 -4
  121. package/dist/clis/constants.mjs.map +1 -1
  122. package/dist/clis/index.d.mts +591 -30
  123. package/dist/clis/index.d.mts.map +1 -1
  124. package/dist/clis/index.mjs +413 -18
  125. package/dist/clis/index.mjs.map +1 -1
  126. package/dist/clis/project-env.d.mts +27 -0
  127. package/dist/clis/project-env.d.mts.map +1 -0
  128. package/dist/clis/project-env.mjs +44 -0
  129. package/dist/clis/project-env.mjs.map +1 -0
  130. package/dist/clis/project-ports.d.mts +40 -0
  131. package/dist/clis/project-ports.d.mts.map +1 -0
  132. package/dist/clis/project-ports.mjs +90 -0
  133. package/dist/clis/project-ports.mjs.map +1 -0
  134. package/dist/{config-loader-19K8n4DO.js → config-loader-B845Hidf.js} +11 -14
  135. package/dist/config-loader-B845Hidf.js.map +1 -0
  136. package/dist/connect/config-loader.d.ts +2 -1
  137. package/dist/connect/config-loader.d.ts.map +1 -1
  138. package/dist/connect/config-loader.js +1 -1
  139. package/dist/connect/index.d.ts +486 -27
  140. package/dist/connect/index.d.ts.map +1 -1
  141. package/dist/connect/index.js +531 -5
  142. package/dist/connect/index.js.map +1 -1
  143. package/dist/connect/json-adapter.d.ts.map +1 -1
  144. package/dist/{constants-C_EQX4DY.d.ts → constants-BP_gjn8g.d.ts} +1 -1
  145. package/dist/constants-BP_gjn8g.d.ts.map +1 -0
  146. package/dist/constants.d.ts +1 -1
  147. package/dist/document-drive/index.d.ts +2 -2
  148. package/dist/document-drive/index.js +3 -3
  149. package/dist/document-drive/index.js.map +1 -1
  150. package/dist/document-model/index.d.ts +4 -5
  151. package/dist/document-model/index.js +1337 -133
  152. package/dist/document-model/index.js.map +1 -1
  153. package/dist/document-model/mock.d.ts +22 -2
  154. package/dist/document-model/mock.d.ts.map +1 -0
  155. package/dist/document-model/mock.js +32 -3
  156. package/dist/document-model/mock.js.map +1 -1
  157. package/dist/document-model/utils.d.ts +1 -2
  158. package/dist/document-model/utils.js +1 -2
  159. package/dist/{index-CQDIrK1k.d.ts → index-C_iVZe7f.d.ts} +1 -1
  160. package/dist/index-C_iVZe7f.d.ts.map +1 -0
  161. package/dist/index-DPuio_se.d.ts +836 -0
  162. package/dist/index-DPuio_se.d.ts.map +1 -0
  163. package/dist/index.d.ts +5 -6
  164. package/dist/processors/index.d.ts +2 -2
  165. package/dist/registry/index.d.ts +5 -4
  166. package/dist/registry/index.d.ts.map +1 -1
  167. package/dist/registry/index.js +9 -8
  168. package/dist/registry/index.js.map +1 -1
  169. package/dist/registry/manifest-slim.d.ts +1 -1
  170. package/dist/registry/urls.d.ts +11 -0
  171. package/dist/registry/urls.d.ts.map +1 -0
  172. package/dist/registry/urls.js +15 -0
  173. package/dist/registry/urls.js.map +1 -0
  174. package/dist/{types-DvWPqxJr.d.ts → types-BBUlASQ7.d.ts} +30 -4
  175. package/dist/types-BBUlASQ7.d.ts.map +1 -0
  176. package/dist/{types-DXsYu6Tq.d.ts → types-BzWRXB7f.d.ts} +507 -16
  177. package/dist/types-BzWRXB7f.d.ts.map +1 -0
  178. package/dist/utils-DP122OSS.d.ts +18 -0
  179. package/dist/utils-DP122OSS.d.ts.map +1 -0
  180. package/dist/{utils-DKOFCM0Q.js → utils-aaTmfxFW.js} +45 -2
  181. package/dist/utils-aaTmfxFW.js.map +1 -0
  182. package/package.json +12 -1
  183. package/dist/clis/args/access-token.d.mts.map +0 -1
  184. package/dist/clis/args/access-token.mjs.map +0 -1
  185. package/dist/clis/args/common-dbsvksvf.mjs.map +0 -1
  186. package/dist/clis/args/connect.d.mts.map +0 -1
  187. package/dist/clis/args/connect.mjs.map +0 -1
  188. package/dist/clis/args/generate.d.mts.map +0 -1
  189. package/dist/clis/args/init.d.mts.map +0 -1
  190. package/dist/clis/args/init.mjs.map +0 -1
  191. package/dist/clis/args/inspect.d.mts.map +0 -1
  192. package/dist/clis/args/inspect.mjs.map +0 -1
  193. package/dist/clis/args/install.d.mts.map +0 -1
  194. package/dist/clis/args/install.mjs.map +0 -1
  195. package/dist/clis/args/list.d.mts.map +0 -1
  196. package/dist/clis/args/list.mjs.map +0 -1
  197. package/dist/clis/args/login.d.mts.map +0 -1
  198. package/dist/clis/args/login.mjs.map +0 -1
  199. package/dist/clis/args/migrate.d.mts.map +0 -1
  200. package/dist/clis/args/migrate.mjs.map +0 -1
  201. package/dist/clis/args/publish.d.mts.map +0 -1
  202. package/dist/clis/args/publish.mjs.map +0 -1
  203. package/dist/clis/args/registry.d.mts.map +0 -1
  204. package/dist/clis/args/registry.mjs.map +0 -1
  205. package/dist/clis/args/service.mjs.map +0 -1
  206. package/dist/clis/args/switchboard.d.mts.map +0 -1
  207. package/dist/clis/args/switchboard.mjs.map +0 -1
  208. package/dist/clis/args/uninstall.d.mts.map +0 -1
  209. package/dist/clis/args/uninstall.mjs.map +0 -1
  210. package/dist/clis/args/unpublish.d.mts.map +0 -1
  211. package/dist/clis/args/unpublish.mjs.map +0 -1
  212. package/dist/clis/args/vetra.d.mts.map +0 -1
  213. package/dist/clis/args/vetra.mjs.map +0 -1
  214. package/dist/config-loader-19K8n4DO.js.map +0 -1
  215. package/dist/constants-C_EQX4DY.d.ts.map +0 -1
  216. package/dist/index-CQDIrK1k.d.ts.map +0 -1
  217. package/dist/index-Dz7JrBXs.d.ts +0 -399
  218. package/dist/index-Dz7JrBXs.d.ts.map +0 -1
  219. package/dist/mock-CBcf78ra.d.ts +0 -7
  220. package/dist/mock-CBcf78ra.d.ts.map +0 -1
  221. package/dist/types-D0NNBVGA.d.ts +0 -167
  222. package/dist/types-D0NNBVGA.d.ts.map +0 -1
  223. package/dist/types-DXsYu6Tq.d.ts.map +0 -1
  224. package/dist/types-DvWPqxJr.d.ts.map +0 -1
  225. package/dist/utils-BEByNOHo.d.ts +0 -9
  226. package/dist/utils-BEByNOHo.d.ts.map +0 -1
  227. package/dist/utils-DKOFCM0Q.js.map +0 -1
@@ -1,10 +1,110 @@
1
- import { a as buildOperationSignatureParams, c as hex2ab, i as buildOperationSignatureMessage, n as generateId, o as getUnixTimestamp, r as ab2hex, s as hashBrowser, t as deriveOperationId } from "../utils-DKOFCM0Q.js";
2
- import { generateMock } from "./mock.js";
1
+ import { a as base58Decode, c as buildOperationSignatureParams, d as hex2ab, i as ab2hex, l as getUnixTimestamp, n as generateId, o as base64UrlToBytes, r as generateMock, s as buildOperationSignatureMessage, t as deriveOperationId, u as hashBrowser } from "../utils-aaTmfxFW.js";
3
2
  import { ZodError, z } from "zod";
4
3
  import { stringify } from "safe-stable-stringify";
5
4
  import { strFromU8, strToU8, unzip, zip } from "fflate";
6
5
  import { castDraft, create, unsafe } from "mutative";
7
6
  import { constantCase, pascalCase } from "change-case";
7
+ //#region document-model/signatures.ts
8
+ /**
9
+ * What separates a signature's params when it travels as one string.
10
+ *
11
+ * GraphQL declares `signatures` as a list of strings, not a list of lists, so a
12
+ * tuple is joined for transport and split on arrival. The separator is here so
13
+ * the two halves cannot disagree about it - they live in different packages, and
14
+ * a mismatch would corrupt every signature that crossed the wire rather than
15
+ * failing outright.
16
+ */
17
+ const SIGNATURE_PARAM_SEPARATOR = ", ";
18
+ /** The number of params a signature carries. */
19
+ const SIGNATURE_PARAM_COUNT = 5;
20
+ /** Joins a signature's params for transport. Already-joined input passes through. */
21
+ function serializeSignature(signature) {
22
+ return Array.isArray(signature) ? signature.join(SIGNATURE_PARAM_SEPARATOR) : signature;
23
+ }
24
+ /**
25
+ * Splits a transported signature back into its params. A tuple passes through.
26
+ *
27
+ * Short input is padded rather than refused: verification reads the params by
28
+ * position and fails on a wrong one, which says more than a length complaint
29
+ * raised here would.
30
+ */
31
+ function deserializeSignature(signature) {
32
+ if (Array.isArray(signature)) return signature;
33
+ const parts = signature.split(SIGNATURE_PARAM_SEPARATOR);
34
+ return Array.from({ length: SIGNATURE_PARAM_COUNT }, (_unused, index) => parts[index] ?? "");
35
+ }
36
+ //#endregion
37
+ //#region document-model/action-transport.ts
38
+ /**
39
+ * Projects an action onto the fields the GraphQL `ActionInput` declares.
40
+ *
41
+ * A projection rather than a spread, because an input object rejects a field it
42
+ * does not declare, and that refusal takes the whole request with it. An action
43
+ * read back out of storage can carry fields the type no longer has - a legacy
44
+ * `attachments` array, or the operation fields left behind by a signing helper
45
+ * that returns an operation - and any one of them would sink an otherwise valid
46
+ * submission.
47
+ *
48
+ * Only fields the action actually carries are emitted, so an unsigned action
49
+ * sends no context at all rather than a context full of nulls.
50
+ */
51
+ function toTransportAction(action) {
52
+ if (action.input === void 0 || action.input === null) throw new Error(`Action ${action.id} (${action.type}) has no input, which the wire requires`);
53
+ const projected = {
54
+ id: action.id,
55
+ type: action.type,
56
+ timestampUtcMs: action.timestampUtcMs,
57
+ input: action.input,
58
+ scope: action.scope
59
+ };
60
+ const context = toTransportContext(action.context);
61
+ return context ? {
62
+ ...projected,
63
+ context
64
+ } : projected;
65
+ }
66
+ function toTransportContext(context) {
67
+ if (!context) return;
68
+ const projected = {};
69
+ if (context.prevOpIndex !== void 0) projected.prevOpIndex = context.prevOpIndex;
70
+ if (context.prevOpHash !== void 0) projected.prevOpHash = context.prevOpHash;
71
+ if (context.nonce !== void 0) projected.nonce = context.nonce;
72
+ const signer = context.signer;
73
+ if (signer) projected.signer = {
74
+ ...signer.user ? { user: toTransportSignerUser(signer.user) } : {},
75
+ ...signer.app ? { app: toTransportSignerApp(signer.app) } : {},
76
+ signatures: (signer.signatures ?? []).map(serializeSignature)
77
+ };
78
+ return Object.keys(projected).length > 0 ? projected : void 0;
79
+ }
80
+ /**
81
+ * The identity, projected for the same reason the context around it is.
82
+ *
83
+ * A signer is handed in by the app, so what reaches here is only as narrow as
84
+ * whoever built it: an identity carrying a session's DID, credential or profile
85
+ * alongside the address is refused by `ReactorSignerUserInput`, and that
86
+ * refusal takes the whole submission with it.
87
+ *
88
+ * The compiler cannot stand in for this. `UserActionSigner` already declares
89
+ * exactly these three fields, but excess-property checks apply to fresh object
90
+ * literals and never to a variable of a wider type, so a wide identity assigned
91
+ * to the narrow type passes untouched.
92
+ */
93
+ function toTransportSignerUser(user) {
94
+ return {
95
+ address: user.address,
96
+ networkId: user.networkId,
97
+ chainId: user.chainId
98
+ };
99
+ }
100
+ /** The signing app, projected on the same rule as the identity above. */
101
+ function toTransportSignerApp(app) {
102
+ return {
103
+ name: app.name,
104
+ key: app.key
105
+ };
106
+ }
107
+ //#endregion
8
108
  //#region document-model/errors.ts
9
109
  const FileSystemError = /* @__PURE__ */ new Error("File system not available.");
10
110
  var InvalidActionInputError = class extends Error {
@@ -39,6 +139,75 @@ var DowngradeNotSupportedError = class extends Error {
39
139
  this.toVersion = toVersion;
40
140
  }
41
141
  };
142
+ /**
143
+ * Thrown when INITIALIZE_AUTH is applied to an already-initialized auth scope.
144
+ * The genesis action is valid only at auth revision zero.
145
+ */
146
+ var AuthAlreadyInitializedError = class extends Error {
147
+ documentId;
148
+ constructor(documentId) {
149
+ super(`Auth scope already initialized for document ${documentId}: INITIALIZE_AUTH is valid only at auth revision zero`);
150
+ this.name = "AuthAlreadyInitializedError";
151
+ this.documentId = documentId;
152
+ }
153
+ };
154
+ /**
155
+ * Thrown when INITIALIZE_AUTH is not signed by the document creator (its signer
156
+ * does not match `header.sig.publicKey`), so it cannot set the auth policy.
157
+ */
158
+ var AuthInitializerNotCreatorError = class extends Error {
159
+ documentId;
160
+ constructor(documentId) {
161
+ super(`INITIALIZE_AUTH for document ${documentId} must be signed by the document creator`);
162
+ this.name = "AuthInitializerNotCreatorError";
163
+ this.documentId = documentId;
164
+ }
165
+ };
166
+ /**
167
+ * Thrown when INITIALIZE_AUTH carries a version below 1. Version 0 is reserved
168
+ * for the uninitialized auth scope.
169
+ */
170
+ var InvalidAuthVersionError = class extends Error {
171
+ documentId;
172
+ version;
173
+ constructor(documentId, version) {
174
+ super(`Invalid auth policy version ${version} for document ${documentId}: INITIALIZE_AUTH requires an integer version >= 1`);
175
+ this.name = "InvalidAuthVersionError";
176
+ this.documentId = documentId;
177
+ this.version = version;
178
+ }
179
+ };
180
+ /** Thrown when a duplicate would lose the source policy's version or creator binding. */
181
+ var AuthPolicyNotPreservedError = class extends Error {
182
+ documentId;
183
+ constructor(documentId) {
184
+ super(`Duplicating document ${documentId} would not preserve its auth policy: the copy loses the policy version or its creator binding`);
185
+ this.name = "AuthPolicyNotPreservedError";
186
+ this.documentId = documentId;
187
+ }
188
+ };
189
+ /**
190
+ * Thrown when a grant referenced by REMOVE_GRANT or MOVE_GRANT does not exist.
191
+ */
192
+ var GrantNotFoundError = class extends Error {
193
+ grantId;
194
+ constructor(grantId) {
195
+ super(`Grant not found in auth scope: ${grantId}`);
196
+ this.name = "GrantNotFoundError";
197
+ this.grantId = grantId;
198
+ }
199
+ };
200
+ /**
201
+ * Thrown when a disallowed action (UNDO, REDO, PRUNE) targets the auth scope.
202
+ */
203
+ var AuthActionNotAllowedError = class extends Error {
204
+ actionType;
205
+ constructor(actionType) {
206
+ super(`${actionType} is not permitted on the auth scope`);
207
+ this.name = "AuthActionNotAllowedError";
208
+ this.actionType = actionType;
209
+ }
210
+ };
42
211
  var HashMismatchError = class extends Error {
43
212
  _scope;
44
213
  _document;
@@ -65,6 +234,25 @@ var HashMismatchError = class extends Error {
65
234
  return this._operation;
66
235
  }
67
236
  };
237
+ /**
238
+ * Thrown when replay or import requires a document model version that is not
239
+ * registered. Carries the data the UI needs to explain the mismatch.
240
+ */
241
+ var UnsupportedDocumentModelVersionError = class extends Error {
242
+ documentType;
243
+ requiredVersion;
244
+ availableVersions;
245
+ constructor(documentType, requiredVersion, availableVersions) {
246
+ super(`No reducer registered for document version ${requiredVersion}. Available versions: ${availableVersions.join(", ")}`);
247
+ this.name = "UnsupportedDocumentModelVersionError";
248
+ this.documentType = documentType;
249
+ this.requiredVersion = requiredVersion;
250
+ this.availableVersions = availableVersions;
251
+ }
252
+ static isError(error) {
253
+ return Error.isError(error) && error.name === "UnsupportedDocumentModelVersionError";
254
+ }
255
+ };
68
256
  //#endregion
69
257
  //#region document-model/schemas.ts
70
258
  const isDefinedNonNullAny = (v) => v !== void 0 && v !== null;
@@ -553,6 +741,89 @@ const ConfigEntrySchema = z.object({
553
741
  required: z.boolean().optional(),
554
742
  default: z.boolean().optional()
555
743
  });
744
+ const PwaUrlPatternSchema = z.union([z.string(), z.strictObject({
745
+ source: z.string(),
746
+ flags: z.string().optional()
747
+ }).refine((p) => {
748
+ try {
749
+ new RegExp(p.source, p.flags);
750
+ return true;
751
+ } catch {
752
+ return false;
753
+ }
754
+ }, { message: "source/flags do not compile to a valid RegExp" })]);
755
+ const PwaRuntimeCachingSchema = z.strictObject({
756
+ urlPattern: PwaUrlPatternSchema,
757
+ handler: z.enum([
758
+ "CacheFirst",
759
+ "CacheOnly",
760
+ "NetworkFirst",
761
+ "NetworkOnly",
762
+ "StaleWhileRevalidate"
763
+ ]),
764
+ method: z.enum([
765
+ "GET",
766
+ "POST",
767
+ "PUT",
768
+ "DELETE",
769
+ "HEAD",
770
+ "PATCH"
771
+ ]).optional(),
772
+ options: z.strictObject({
773
+ cacheName: z.string().optional(),
774
+ networkTimeoutSeconds: z.number().optional(),
775
+ expiration: z.strictObject({
776
+ maxEntries: z.number().optional(),
777
+ maxAgeSeconds: z.number().optional()
778
+ }).optional(),
779
+ cacheableResponse: z.strictObject({
780
+ statuses: z.array(z.number()).optional(),
781
+ headers: z.record(z.string(), z.string()).optional()
782
+ }).optional()
783
+ }).optional()
784
+ });
785
+ const PwaIconSchema = z.strictObject({
786
+ src: z.string(),
787
+ sizes: z.string().optional(),
788
+ type: z.string().optional(),
789
+ purpose: z.string().optional()
790
+ });
791
+ const PwaFileHandlerSchema = z.strictObject({
792
+ accept: z.record(z.string(), z.array(z.string().regex(/^\./, "file extensions must start with '.'"))),
793
+ icons: z.array(PwaIconSchema).optional(),
794
+ launch_type: z.enum(["single-client", "multiple-clients"]).optional()
795
+ });
796
+ const PwaManifestOverrideSchema = z.strictObject({
797
+ name: z.string().optional(),
798
+ short_name: z.string().optional(),
799
+ description: z.string().optional(),
800
+ theme_color: z.string().optional(),
801
+ background_color: z.string().optional(),
802
+ display: z.enum([
803
+ "fullscreen",
804
+ "standalone",
805
+ "minimal-ui",
806
+ "browser"
807
+ ]).optional(),
808
+ start_url: z.string().optional(),
809
+ scope: z.string().optional(),
810
+ icons: z.array(PwaIconSchema).optional(),
811
+ file_handlers: z.array(PwaFileHandlerSchema).optional(),
812
+ launch_handler: z.strictObject({ client_mode: z.enum([
813
+ "auto",
814
+ "focus-existing",
815
+ "navigate-existing",
816
+ "navigate-new"
817
+ ]) }).optional()
818
+ });
819
+ const PwaConfigSchema = z.strictObject({
820
+ manifest: PwaManifestOverrideSchema.optional(),
821
+ globPatterns: z.array(z.string()).optional(),
822
+ globIgnores: z.array(z.string()).optional(),
823
+ maximumFileSizeToCacheInBytes: z.number().optional(),
824
+ runtimeCaching: z.array(PwaRuntimeCachingSchema).optional(),
825
+ navigateFallbackDenylist: z.array(PwaUrlPatternSchema).optional()
826
+ });
556
827
  const ManifestSchema = z.object({
557
828
  name: z.string(),
558
829
  description: z.string().optional(),
@@ -564,7 +835,8 @@ const ManifestSchema = z.object({
564
835
  editors: PowerhouseModulesSchema,
565
836
  processors: PowerhouseModulesSchema,
566
837
  subgraphs: PowerhouseModulesSchema,
567
- config: z.array(ConfigEntrySchema).optional()
838
+ config: z.array(ConfigEntrySchema).optional(),
839
+ pwa: PwaConfigSchema.optional()
568
840
  });
569
841
  //#endregion
570
842
  //#region document-model/actions.ts
@@ -850,6 +1122,539 @@ const actions = {
850
1122
  ...documentModelActions
851
1123
  };
852
1124
  //#endregion
1125
+ //#region document-model/document-type.ts
1126
+ const documentModelDocumentType = "powerhouse/document-model";
1127
+ const groupDocumentType = "powerhouse/reactor-group";
1128
+ /**
1129
+ * The group-model action types that change membership. The groups projection
1130
+ * filters its reads to these, so any other group operation is invisible to a
1131
+ * decision. Kept here so the reactor never depends on the group package; a
1132
+ * reactor-group test guards against drift.
1133
+ */
1134
+ const groupMembershipActionTypes = ["ADD_MEMBER", "REMOVE_MEMBER"];
1135
+ //#endregion
1136
+ //#region document-model/auth-v1.ts
1137
+ /** Maximum number of grants in a policy. */
1138
+ const MAX_AUTH_GRANTS = 100;
1139
+ /** Maximum nesting depth of a condition tree. */
1140
+ const MAX_CONDITION_DEPTH = 10;
1141
+ /** Maximum node count (conditions plus operands) of a condition tree. */
1142
+ const MAX_CONDITION_NODES = 100;
1143
+ /** Maximum entries in an execute capability's operation list. */
1144
+ const MAX_CAPABILITY_OPERATIONS = 100;
1145
+ /**
1146
+ * Thrown when a grant violates the v1 validation rules. The message is stored
1147
+ * on error operations, so it must be a pure function of the input.
1148
+ */
1149
+ var InvalidGrantError = class extends Error {
1150
+ grantId;
1151
+ constructor(grantId, problem) {
1152
+ super(`Invalid grant "${grantId}": ${problem}`);
1153
+ this.name = "InvalidGrantError";
1154
+ this.grantId = grantId;
1155
+ }
1156
+ };
1157
+ /** Thrown for a `{ group }` principal on a group document: references never chain. */
1158
+ var GroupPrincipalNotAllowedError = class extends Error {
1159
+ grantId;
1160
+ constructor(grantId) {
1161
+ super(`Grant "${grantId}" uses a group principal on a group document: a group's auth scope cannot reference other groups`);
1162
+ this.name = "GroupPrincipalNotAllowedError";
1163
+ this.grantId = grantId;
1164
+ }
1165
+ };
1166
+ /**
1167
+ * Thrown when a change would leave a creator-less policy with no grant
1168
+ * permitting execute on the auth scope. Without the creator carve-out no
1169
+ * subject could ever administer such a policy again.
1170
+ */
1171
+ var AuthAdministrationLockoutError = class extends Error {
1172
+ grantId;
1173
+ constructor(grantId) {
1174
+ super(`Change to grant "${grantId}" would leave no reachable grant permitting execute on the auth scope: a policy with no creator must always retain one`);
1175
+ this.name = "AuthAdministrationLockoutError";
1176
+ this.grantId = grantId;
1177
+ }
1178
+ };
1179
+ /**
1180
+ * Thrown when INITIALIZE_AUTH would create a creator-less policy with no grant
1181
+ * permitting execute on the auth scope. Such a policy would be born with no
1182
+ * subject able to administer it.
1183
+ */
1184
+ var AuthAdministrationMissingError = class extends Error {
1185
+ constructor() {
1186
+ super("Initial grants include no reachable grant permitting execute on the auth scope: a policy with no creator must always include one");
1187
+ this.name = "AuthAdministrationMissingError";
1188
+ }
1189
+ };
1190
+ const GRANT_KEYS = new Set([
1191
+ "id",
1192
+ "description",
1193
+ "effect",
1194
+ "principal",
1195
+ "capability",
1196
+ "where"
1197
+ ]);
1198
+ const PRINCIPAL_KINDS = new Set([
1199
+ "anyone",
1200
+ "address",
1201
+ "group",
1202
+ "match"
1203
+ ]);
1204
+ const COMPARISON_CONDITION_KINDS = new Set([
1205
+ "eq",
1206
+ "ne",
1207
+ "lt",
1208
+ "lte",
1209
+ "gt",
1210
+ "gte"
1211
+ ]);
1212
+ function isPlainValue(value) {
1213
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1214
+ }
1215
+ function operandProblem(value, capabilityScope, budget) {
1216
+ budget.nodes -= 1;
1217
+ if (budget.nodes < 0) return `condition exceeds 100 nodes`;
1218
+ if (!isPlainValue(value)) return "operand must be an object";
1219
+ const keys = Object.keys(value);
1220
+ if (keys.length !== 1) return "operand must have exactly one of attr or lit";
1221
+ if (keys[0] === "attr") {
1222
+ const attr = value.attr;
1223
+ if (typeof attr !== "string" || attr.length === 0) return "attr must be a non-empty string";
1224
+ if (capabilityScope !== void 0 && capabilityScope !== "*" && attr.startsWith("doc.")) {
1225
+ const pathScope = attr.split(".")[1] ?? "";
1226
+ if (pathScope !== capabilityScope) return `condition path "${attr}" reads scope "${pathScope}" but the capability covers only scope "${capabilityScope}"`;
1227
+ }
1228
+ return null;
1229
+ }
1230
+ if (keys[0] === "lit") {
1231
+ const lit = value.lit;
1232
+ if (lit !== null && typeof lit !== "string" && typeof lit !== "number" && typeof lit !== "boolean") return "lit must be a string, number, boolean, or null";
1233
+ if (typeof lit === "number" && !Number.isFinite(lit)) return "lit must be a finite number";
1234
+ if (typeof lit === "number" && Object.is(lit, -0)) return "lit must not be negative zero";
1235
+ return null;
1236
+ }
1237
+ return `unknown operand kind "${keys[0]}"`;
1238
+ }
1239
+ function conditionProblem(value, capabilityScope, depth, budget) {
1240
+ if (depth > 10) return `condition exceeds depth 10`;
1241
+ budget.nodes -= 1;
1242
+ if (budget.nodes < 0) return `condition exceeds 100 nodes`;
1243
+ if (!isPlainValue(value)) return "condition must be an object";
1244
+ const keys = Object.keys(value);
1245
+ if (keys.length !== 1) return "condition must have exactly one operator";
1246
+ const kind = keys[0];
1247
+ const body = value[kind];
1248
+ if (COMPARISON_CONDITION_KINDS.has(kind)) {
1249
+ if (!Array.isArray(body) || body.length !== 2) return `${kind} requires a pair of operands`;
1250
+ for (const operand of body) {
1251
+ const problem = operandProblem(operand, capabilityScope, budget);
1252
+ if (problem !== null) return problem;
1253
+ }
1254
+ return null;
1255
+ }
1256
+ if (kind === "in" || kind === "notIn") {
1257
+ if (!Array.isArray(body) || body.length !== 2 || !Array.isArray(body[1])) return `${kind} requires an operand and an operand list`;
1258
+ const first = operandProblem(body[0], capabilityScope, budget);
1259
+ if (first !== null) return first;
1260
+ for (const operand of body[1]) {
1261
+ const problem = operandProblem(operand, capabilityScope, budget);
1262
+ if (problem !== null) return problem;
1263
+ }
1264
+ return null;
1265
+ }
1266
+ if (kind === "exists") return operandProblem(body, capabilityScope, budget);
1267
+ if (kind === "and" || kind === "or") {
1268
+ if (!Array.isArray(body)) return `${kind} requires a condition list`;
1269
+ for (const child of body) {
1270
+ const problem = conditionProblem(child, capabilityScope, depth + 1, budget);
1271
+ if (problem !== null) return problem;
1272
+ }
1273
+ return null;
1274
+ }
1275
+ if (kind === "not") return conditionProblem(body, capabilityScope, depth + 1, budget);
1276
+ return `unknown condition operator "${kind}"`;
1277
+ }
1278
+ function principalProblem(value, capabilityScope) {
1279
+ if (!isPlainValue(value)) return "principal must be an object";
1280
+ const keys = Object.keys(value);
1281
+ if (keys.length !== 1 || !PRINCIPAL_KINDS.has(keys[0])) return "principal must have exactly one of anyone, address, group, or match";
1282
+ const kind = keys[0];
1283
+ if (kind === "anyone" && value.anyone !== true) return "anyone must be true";
1284
+ if (kind === "address") {
1285
+ const address = value.address;
1286
+ if (typeof address !== "string" || address.length === 0) return "address must be a non-empty string";
1287
+ }
1288
+ if (kind === "group") {
1289
+ const group = value.group;
1290
+ if (typeof group !== "string" || group.length === 0) return "group must be a non-empty string";
1291
+ }
1292
+ if (kind === "match") return conditionProblem(value.match, capabilityScope, 1, { nodes: 100 });
1293
+ return null;
1294
+ }
1295
+ function capabilityProblem(value) {
1296
+ if (!isPlainValue(value)) return "capability must be an object";
1297
+ const can = value.can;
1298
+ if (can !== "read" && can !== "execute") return "capability.can must be read or execute";
1299
+ const allowedKeys = can === "execute" ? [
1300
+ "can",
1301
+ "scope",
1302
+ "operation"
1303
+ ] : ["can", "scope"];
1304
+ const unknownKeys = Object.keys(value).filter((key) => !allowedKeys.includes(key)).sort();
1305
+ if (unknownKeys.length > 0) return `unknown capability key "${unknownKeys[0]}"`;
1306
+ if (value.scope !== void 0) {
1307
+ if (typeof value.scope !== "string" || value.scope.length === 0) return "capability.scope must be a non-empty string";
1308
+ }
1309
+ if (can === "execute" && value.operation !== void 0) {
1310
+ const operation = value.operation;
1311
+ if (!Array.isArray(operation)) return "capability.operation must be an array";
1312
+ if (operation.length > 100) return `capability.operation exceeds 100 entries`;
1313
+ for (const entry of operation) if (typeof entry !== "string" || entry.length === 0) return "capability.operation entries must be non-empty strings";
1314
+ }
1315
+ return null;
1316
+ }
1317
+ /** Returns the first v1-rule violation, or null. Pure, total, deterministic. */
1318
+ function grantProblem(value) {
1319
+ if (!isPlainValue(value)) return "grant must be an object";
1320
+ const unknownKeys = Object.keys(value).filter((key) => !GRANT_KEYS.has(key)).sort();
1321
+ if (unknownKeys.length > 0) return `unknown grant key "${unknownKeys[0]}"`;
1322
+ if (typeof value.id !== "string" || value.id.length === 0) return "id must be a non-empty string";
1323
+ if (typeof value.description !== "string") return "description must be a string";
1324
+ if (value.effect !== "allow" && value.effect !== "deny") return "effect must be allow or deny";
1325
+ const capabilityValue = value.capability;
1326
+ const capability = capabilityProblem(capabilityValue);
1327
+ if (capability !== null) return capability;
1328
+ const capabilityScope = capabilityValue.scope;
1329
+ const principal = principalProblem(value.principal, capabilityScope);
1330
+ if (principal !== null) return principal;
1331
+ if (value.where !== void 0) return conditionProblem(value.where, capabilityScope, 1, { nodes: 100 });
1332
+ return null;
1333
+ }
1334
+ const GrantSchema = () => z.custom((value) => grantProblem(value) === null);
1335
+ /** V1 shape rules plus the group-document group-principal ban. */
1336
+ function assertValidGrant(grant, documentType) {
1337
+ const grantId = isPlainValue(grant) && typeof grant.id === "string" ? grant.id : "";
1338
+ const problem = grantProblem(grant);
1339
+ if (problem !== null) throw new InvalidGrantError(grantId, problem);
1340
+ if (documentType === "powerhouse/reactor-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
1341
+ }
1342
+ /**
1343
+ * Validates an initial grant list: the count cap, every grant, and — on a
1344
+ * creator-less policy — that some grant keeps the auth scope administrable.
1345
+ */
1346
+ function assertValidInitialGrants(grants, documentType, creator) {
1347
+ if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
1348
+ for (const grant of grants) assertValidGrant(grant, documentType);
1349
+ if (creator === void 0 && !administrationReachable(grants)) throw new AuthAdministrationMissingError();
1350
+ }
1351
+ /**
1352
+ * Validates a grant upsert: the grant itself, the count cap on append, and
1353
+ * administration retention. Retention is checked on an append as well as an
1354
+ * in-place replace, because a grant appended after the administration grant can
1355
+ * shadow it (evaluation is last-applicable-grant-wins) and so take
1356
+ * administration away without removing anything.
1357
+ */
1358
+ function assertValidGrantUpsert(grant, existing, documentType, creator) {
1359
+ assertValidGrant(grant, documentType);
1360
+ const exists = existing.some((g) => g.id === grant.id);
1361
+ if (!exists && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
1362
+ assertAuthAdministrationRetained(creator, existing, exists ? existing.map((g) => g.id === grant.id ? grant : g) : [...existing, grant], grant.id);
1363
+ }
1364
+ /**
1365
+ * The request whose coverage keeps a policy administrable: a subject who may
1366
+ * SET_GRANT can upsert any grant, so every other repair stays reachable.
1367
+ */
1368
+ const AUTH_ADMINISTRATION_REQUEST = {
1369
+ verb: "execute",
1370
+ scope: "auth",
1371
+ operation: "SET_GRANT"
1372
+ };
1373
+ /**
1374
+ * Whether some subject can still administer the auth scope under this grant
1375
+ * list.
1376
+ *
1377
+ * Answers exactly what asking {@link evaluateGrantStack} per candidate grant
1378
+ * answered, in one reverse pass instead of one full stack scan per candidate.
1379
+ * Evaluation is last-applicable-grant-wins, so scanning from the end meets each
1380
+ * subject's deciding grant first: an anyone grant decides every subject not
1381
+ * already decided, and an allow reached that way is itself a grant that carries
1382
+ * administration. Only anyone and address principals are candidates, because
1383
+ * those are the ones v1 can match with no groups and no condition context; a
1384
+ * `where` condition or a group or match principal never applies.
1385
+ */
1386
+ function administrationReachable(grants) {
1387
+ const shadowedAddresses = /* @__PURE__ */ new Set();
1388
+ for (let index = grants.length - 1; index >= 0; index -= 1) {
1389
+ const grant = grants[index];
1390
+ if (grant.where !== void 0 || !grantAnswers(grant, AUTH_ADMINISTRATION_REQUEST)) continue;
1391
+ const allows = grant.effect === "allow";
1392
+ if ("anyone" in grant.principal) return allows;
1393
+ if (!("address" in grant.principal)) continue;
1394
+ const address = grant.principal.address.toLowerCase();
1395
+ if (shadowedAddresses.has(address)) continue;
1396
+ if (allows) return true;
1397
+ shadowedAddresses.add(address);
1398
+ }
1399
+ return false;
1400
+ }
1401
+ /**
1402
+ * A creator-less policy must always retain a grant permitting execute on the
1403
+ * auth scope; on a signed document the creator carve-out keeps administration
1404
+ * reachable instead. Rejects a change that takes the last such grant away. A
1405
+ * policy already without one is left alone: the change is not what locks it.
1406
+ */
1407
+ function assertAuthAdministrationRetained(creator, previous, next, grantId) {
1408
+ if (creator !== void 0) return;
1409
+ if (administrationReachable(previous) && !administrationReachable(next)) throw new AuthAdministrationLockoutError(grantId);
1410
+ }
1411
+ /**
1412
+ * An operand whose shape validation would have rejected. Distinguished from
1413
+ * an unresolved path so a structurally malformed operand poisons its whole
1414
+ * condition to false rather than reading as "absent", which `not` would
1415
+ * otherwise widen to true.
1416
+ */
1417
+ const INVALID_OPERAND = Symbol("invalid-operand");
1418
+ /**
1419
+ * Narrows to the values conditions compare. An object, array, or non-finite
1420
+ * number resolves to undefined, and every comparison involving undefined is
1421
+ * false.
1422
+ */
1423
+ function asConditionValue(value) {
1424
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
1425
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1426
+ }
1427
+ /**
1428
+ * Resolves one operand. Attr roots: `subject.*`, `doc.<scope>.*` where the
1429
+ * scope must be the executing scope (validation already rejects any other,
1430
+ * but resolution stays total), and `action.input.*`. Path steps read own
1431
+ * properties only, so prototype members can never influence a verdict.
1432
+ */
1433
+ function resolveOperand(operand, subject, request, conditions) {
1434
+ if (!isPlainValue(operand)) return INVALID_OPERAND;
1435
+ const keys = Object.keys(operand);
1436
+ if (keys.length !== 1) return INVALID_OPERAND;
1437
+ if (keys[0] === "lit") {
1438
+ const value = asConditionValue(operand.lit);
1439
+ return value === void 0 ? INVALID_OPERAND : value;
1440
+ }
1441
+ if (keys[0] !== "attr") return INVALID_OPERAND;
1442
+ const attr = operand.attr;
1443
+ if (typeof attr !== "string" || attr.length === 0) return INVALID_OPERAND;
1444
+ const path = attr.split(".");
1445
+ let value;
1446
+ let rest;
1447
+ if (path[0] === "subject") {
1448
+ value = subject;
1449
+ rest = path.slice(1);
1450
+ } else if (path[0] === "doc") {
1451
+ if (path[1] !== request.scope) return;
1452
+ value = conditions.scopeState;
1453
+ rest = path.slice(2);
1454
+ } else if (path[0] === "action" && path[1] === "input") {
1455
+ value = conditions.actionInput;
1456
+ rest = path.slice(2);
1457
+ } else return;
1458
+ for (const segment of rest) {
1459
+ if (!isPlainValue(value) || !Object.hasOwn(value, segment)) return;
1460
+ value = value[segment];
1461
+ }
1462
+ return asConditionValue(value);
1463
+ }
1464
+ /**
1465
+ * Total order within one type: numbers numerically, strings by code point.
1466
+ * Everything else, including mixed types, does not order.
1467
+ */
1468
+ function compareValues(left, right) {
1469
+ if (typeof left === "number" && typeof right === "number") return left < right ? -1 : left > right ? 1 : 0;
1470
+ if (typeof left === "string" && typeof right === "string") {
1471
+ const leftPoints = Array.from(left);
1472
+ const rightPoints = Array.from(right);
1473
+ const shared = Math.min(leftPoints.length, rightPoints.length);
1474
+ for (let i = 0; i < shared; i++) {
1475
+ const a = leftPoints[i].codePointAt(0) ?? 0;
1476
+ const b = rightPoints[i].codePointAt(0) ?? 0;
1477
+ if (a !== b) return a < b ? -1 : 1;
1478
+ }
1479
+ return leftPoints.length === rightPoints.length ? 0 : leftPoints.length < rightPoints.length ? -1 : 1;
1480
+ }
1481
+ }
1482
+ /**
1483
+ * Tri-state evaluation: undefined marks a structurally invalid node, which
1484
+ * poisons the whole tree to false at the top — and a structurally malformed
1485
+ * operand poisons its condition the same way. Both are distinct from an
1486
+ * operand whose path fails to resolve, which is a valid comparison that is
1487
+ * false. The distinction keeps `not` from widening over malformed input.
1488
+ */
1489
+ function evaluateNode(node, subject, request, conditions) {
1490
+ if (!isPlainValue(node)) return;
1491
+ const keys = Object.keys(node);
1492
+ if (keys.length !== 1) return;
1493
+ const kind = keys[0];
1494
+ const body = node[kind];
1495
+ switch (kind) {
1496
+ case "eq":
1497
+ case "ne":
1498
+ case "lt":
1499
+ case "lte":
1500
+ case "gt":
1501
+ case "gte": {
1502
+ if (!Array.isArray(body) || body.length !== 2) return;
1503
+ const left = resolveOperand(body[0], subject, request, conditions);
1504
+ const right = resolveOperand(body[1], subject, request, conditions);
1505
+ if (left === INVALID_OPERAND || right === INVALID_OPERAND) return;
1506
+ if (left === void 0 || right === void 0) return false;
1507
+ if (kind === "eq") return left === right;
1508
+ if (kind === "ne") return left !== right;
1509
+ const order = compareValues(left, right);
1510
+ if (order === void 0) return false;
1511
+ switch (kind) {
1512
+ case "lt": return order < 0;
1513
+ case "lte": return order <= 0;
1514
+ case "gt": return order > 0;
1515
+ case "gte": return order >= 0;
1516
+ }
1517
+ return;
1518
+ }
1519
+ case "in":
1520
+ case "notIn": {
1521
+ if (!Array.isArray(body) || body.length !== 2 || !Array.isArray(body[1])) return;
1522
+ const left = resolveOperand(body[0], subject, request, conditions);
1523
+ if (left === INVALID_OPERAND) return;
1524
+ const elements = body[1].map((element) => resolveOperand(element, subject, request, conditions));
1525
+ if (elements.some((value) => value === INVALID_OPERAND)) return;
1526
+ if (left === void 0) return false;
1527
+ const found = elements.some((value) => value !== void 0 && value === left);
1528
+ return kind === "in" ? found : !found;
1529
+ }
1530
+ case "exists": {
1531
+ const value = resolveOperand(body, subject, request, conditions);
1532
+ if (value === INVALID_OPERAND) return;
1533
+ return value !== void 0;
1534
+ }
1535
+ case "and":
1536
+ case "or": {
1537
+ if (!Array.isArray(body)) return;
1538
+ let result = kind === "and";
1539
+ for (const child of body) {
1540
+ const value = evaluateNode(child, subject, request, conditions);
1541
+ if (value === void 0) return;
1542
+ if (kind === "and") result = result && value;
1543
+ else result = result || value;
1544
+ }
1545
+ return result;
1546
+ }
1547
+ case "not": {
1548
+ const value = evaluateNode(body, subject, request, conditions);
1549
+ return value === void 0 ? void 0 : !value;
1550
+ }
1551
+ default: return;
1552
+ }
1553
+ }
1554
+ /**
1555
+ * Evaluates a version-1 condition. Deterministic, total, and pure: any input
1556
+ * shape yields a boolean and never throws, and a malformed condition is
1557
+ * false. These are consensus semantics, versioned by `PHAuthState.version`;
1558
+ * changing them requires a new version.
1559
+ */
1560
+ function evaluateCondition(condition, subject, request, conditions) {
1561
+ return evaluateNode(condition, subject, request, conditions) === true;
1562
+ }
1563
+ /** Whether a capability's scope reaches the requested one. */
1564
+ function scopeCovers(scope, requested) {
1565
+ return scope === void 0 || scope === "*" || scope === requested;
1566
+ }
1567
+ /**
1568
+ * Whether one grant answers this request.
1569
+ *
1570
+ * A grant allowing execute on a scope also allows reading it: executing an
1571
+ * operation means reading the state it applies to, so permitting the write while
1572
+ * withholding the read would describe an access nobody could use. The converse
1573
+ * does not hold -- a read grant confers no write.
1574
+ *
1575
+ * Only an allow carries across. A deny on execute withholds the write and says
1576
+ * nothing about the read, so a policy locking writes down does not silently
1577
+ * revoke a read grant sitting before it. The operation list is not consulted
1578
+ * either: it restricts which operations may be executed, not whether the scope
1579
+ * is visible, and a read carries no operation to match against.
1580
+ *
1581
+ * Reads are not consensus -- no replica records a read, and the two read call
1582
+ * sites are both inside the read gate -- so this rule is not part of what makes
1583
+ * an operation valid, and does not need a policy version of its own.
1584
+ */
1585
+ function grantAnswers(grant, request) {
1586
+ if (capabilityCovers(grant.capability, request)) return true;
1587
+ return request.verb === "read" && grant.effect === "allow" && grant.capability.can === "execute" && scopeCovers(grant.capability.scope, request.scope);
1588
+ }
1589
+ function capabilityCovers(capability, request) {
1590
+ if (capability.can !== request.verb) return false;
1591
+ if (!scopeCovers(capability.scope, request.scope)) return false;
1592
+ if (capability.can === "execute") {
1593
+ if (capability.operation === void 0) return true;
1594
+ return request.operation !== void 0 && capability.operation.includes(request.operation);
1595
+ }
1596
+ return true;
1597
+ }
1598
+ function principalMatches(principal, subject, request, groups, conditions) {
1599
+ if ("anyone" in principal) return true;
1600
+ if ("address" in principal) return subject.address !== void 0 && subject.address.toLowerCase() === principal.address.toLowerCase();
1601
+ if ("group" in principal) {
1602
+ if (groups === void 0 || subject.address === void 0) return false;
1603
+ const group = groups[principal.group];
1604
+ if (group === void 0 || !Array.isArray(group.members)) return false;
1605
+ const address = subject.address.toLowerCase();
1606
+ return group.members.some((member) => member.toLowerCase() === address);
1607
+ }
1608
+ if ("match" in principal) {
1609
+ if (conditions === void 0) return false;
1610
+ return evaluateCondition(principal.match, subject, request, conditions);
1611
+ }
1612
+ return false;
1613
+ }
1614
+ /**
1615
+ * The group document ids named by `{ group }` principals in a grant list, in
1616
+ * order of first appearance. These are the streams the groups projection reads.
1617
+ */
1618
+ function referencedGroupIds(grants) {
1619
+ const ids = [];
1620
+ for (const grant of grants) if ("group" in grant.principal && !ids.includes(grant.principal.group)) ids.push(grant.principal.group);
1621
+ return ids;
1622
+ }
1623
+ /**
1624
+ * Evaluates a v1 grant stack: default deny, last applicable grant wins, and
1625
+ * reports which grant decided it. Group principals match only against a
1626
+ * supplied groups map, and `where` clauses and { match } principals evaluate
1627
+ * only against a supplied condition context; a grant that uses an unsupplied
1628
+ * feature never applies.
1629
+ */
1630
+ function evaluateGrantStack(grants, subject, request, groups, conditions) {
1631
+ let applicable;
1632
+ for (const grant of grants) {
1633
+ if (grant.where !== void 0) {
1634
+ if (conditions === void 0) continue;
1635
+ if (!evaluateCondition(grant.where, subject, request, conditions)) continue;
1636
+ }
1637
+ if (grantAnswers(grant, request) && principalMatches(grant.principal, subject, request, groups, conditions)) applicable = grant;
1638
+ }
1639
+ if (applicable === void 0) return {
1640
+ decision: "deny",
1641
+ refusal: "no-applicable-grant"
1642
+ };
1643
+ if (applicable.effect === "deny") return {
1644
+ decision: "deny",
1645
+ refusal: "denied-by-grant",
1646
+ grantId: applicable.id
1647
+ };
1648
+ return { decision: "allow" };
1649
+ }
1650
+ /**
1651
+ * Evaluates a v1 grant stack: default deny, last applicable grant wins. This is
1652
+ * {@link evaluateGrantStack} with the reason dropped.
1653
+ */
1654
+ function evaluateGrants(grants, subject, request, groups, conditions) {
1655
+ return evaluateGrantStack(grants, subject, request, groups, conditions).decision;
1656
+ }
1657
+ //#endregion
853
1658
  //#region document-model/constants.ts
854
1659
  const documentModelFileExtension = "phdm";
855
1660
  const documentModelInitialLocalState = {};
@@ -1436,8 +2241,403 @@ const HASH_ALGORITHM_SHA512 = "sha512";
1436
2241
  const HASH_ENCODING_BASE64 = "base64";
1437
2242
  const HASH_ENCODING_HEX = "hex";
1438
2243
  //#endregion
1439
- //#region document-model/document-type.ts
1440
- const documentModelDocumentType = "powerhouse/document-model";
2244
+ //#region document-model/state.ts
2245
+ /**
2246
+ * Creates a default PHAuthState
2247
+ */
2248
+ function defaultAuthState() {
2249
+ return {
2250
+ version: 0,
2251
+ grants: []
2252
+ };
2253
+ }
2254
+ /**
2255
+ * Creates a default PHDocumentState
2256
+ */
2257
+ function defaultDocumentState() {
2258
+ return {
2259
+ version: 0,
2260
+ hash: {
2261
+ algorithm: HASH_ALGORITHM_SHA1,
2262
+ encoding: HASH_ENCODING_BASE64
2263
+ }
2264
+ };
2265
+ }
2266
+ /**
2267
+ * Creates a default PHBaseState with auth and document properties
2268
+ */
2269
+ function defaultBaseState() {
2270
+ return {
2271
+ auth: defaultAuthState(),
2272
+ document: defaultDocumentState()
2273
+ };
2274
+ }
2275
+ /**
2276
+ * Creates a PHAuthState with the given properties
2277
+ */
2278
+ function createAuthState(auth) {
2279
+ return {
2280
+ ...defaultAuthState(),
2281
+ ...auth
2282
+ };
2283
+ }
2284
+ /**
2285
+ * Creates a PHDocumentState with the given properties
2286
+ */
2287
+ function createDocumentState(document) {
2288
+ return {
2289
+ ...defaultDocumentState(),
2290
+ ...document
2291
+ };
2292
+ }
2293
+ /**
2294
+ * Creates a PHBaseState with the given auth and document properties
2295
+ */
2296
+ function createBaseState(auth, document) {
2297
+ return {
2298
+ auth: createAuthState(auth),
2299
+ document: createDocumentState(document)
2300
+ };
2301
+ }
2302
+ /**
2303
+ * Backfills the auth scope to the default for legacy documents serialized with
2304
+ * an empty `auth`. Replaces only `state.auth`. Idempotent.
2305
+ */
2306
+ function backfillAuthState(state) {
2307
+ return {
2308
+ ...state,
2309
+ auth: createAuthState(state.auth)
2310
+ };
2311
+ }
2312
+ function defaultGlobalState() {
2313
+ return {
2314
+ ...defaultBaseState(),
2315
+ author: {
2316
+ name: "",
2317
+ website: ""
2318
+ },
2319
+ description: "",
2320
+ extension: "",
2321
+ id: "",
2322
+ name: "",
2323
+ specifications: []
2324
+ };
2325
+ }
2326
+ function defaultLocalState() {
2327
+ return {};
2328
+ }
2329
+ function defaultPHState() {
2330
+ return {
2331
+ ...defaultBaseState(),
2332
+ global: defaultGlobalState(),
2333
+ local: defaultLocalState()
2334
+ };
2335
+ }
2336
+ function createGlobalState(state) {
2337
+ return {
2338
+ ...defaultGlobalState(),
2339
+ ...state || {}
2340
+ };
2341
+ }
2342
+ function createLocalState(state) {
2343
+ return {
2344
+ ...defaultLocalState(),
2345
+ ...state || {}
2346
+ };
2347
+ }
2348
+ function createState(baseState, globalState, localState) {
2349
+ return {
2350
+ ...createBaseState(baseState?.auth, baseState?.document),
2351
+ global: createGlobalState(globalState),
2352
+ local: createLocalState(localState)
2353
+ };
2354
+ }
2355
+ //#endregion
2356
+ //#region document-model/auth.ts
2357
+ const AUTH_ACTION_TYPES = [
2358
+ "INITIALIZE_AUTH",
2359
+ "SET_GRANT",
2360
+ "REMOVE_GRANT",
2361
+ "MOVE_GRANT"
2362
+ ];
2363
+ function isAuthAction(action) {
2364
+ return AUTH_ACTION_TYPES.includes(action.type);
2365
+ }
2366
+ /** Highest known policy version; decide() fails closed above it. */
2367
+ const MAX_SUPPORTED_AUTH_VERSION = 1;
2368
+ const InitializeAuthActionInputSchema = () => z.object({
2369
+ version: z.number().int().min(1),
2370
+ grants: z.array(GrantSchema()).max(100)
2371
+ });
2372
+ const SetGrantActionInputSchema = () => z.object({ grant: GrantSchema() });
2373
+ const RemoveGrantActionInputSchema = () => z.object({ id: z.string() });
2374
+ const MoveGrantActionInputSchema = () => z.object({
2375
+ id: z.string(),
2376
+ index: z.number()
2377
+ });
2378
+ const initializeAuth = (input) => createAction("INITIALIZE_AUTH", input, void 0, InitializeAuthActionInputSchema, "auth");
2379
+ const setGrant = (input) => createAction("SET_GRANT", input, void 0, SetGrantActionInputSchema, "auth");
2380
+ const removeGrant = (input) => createAction("REMOVE_GRANT", input, void 0, RemoveGrantActionInputSchema, "auth");
2381
+ const moveGrant = (input) => createAction("MOVE_GRANT", input, void 0, MoveGrantActionInputSchema, "auth");
2382
+ /**
2383
+ * Destructuring a null input (reachable via raw synced operations) would
2384
+ * store an engine-specific TypeError message on the error operation.
2385
+ */
2386
+ function assertActionInputShape(input) {
2387
+ if (!isPlainValue(input)) throw new InvalidActionInputError({ input: "must be an object" });
2388
+ }
2389
+ function withGrants(document, grants) {
2390
+ return {
2391
+ ...document,
2392
+ state: {
2393
+ ...document.state,
2394
+ auth: {
2395
+ ...document.state.auth,
2396
+ grants
2397
+ }
2398
+ }
2399
+ };
2400
+ }
2401
+ const P256_PUBKEY_MULTICODEC = [128, 36];
2402
+ const DID_KEY_PREFIX = "did:key:z";
2403
+ function bytesEqual(a, b) {
2404
+ if (a.length !== b.length) return false;
2405
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
2406
+ return true;
2407
+ }
2408
+ /**
2409
+ * True when `signerKey` (an ActionSigner app key, a did:key) identifies the same
2410
+ * key recorded as the document creator. Returns false
2411
+ * when there is no creator (empty JWK) or no signer key.
2412
+ */
2413
+ function isDocumentCreator(creatorKey, signerKey) {
2414
+ if (!creatorKey?.x || !creatorKey.y) return false;
2415
+ if (!signerKey || !signerKey.startsWith(DID_KEY_PREFIX)) return false;
2416
+ const decoded = base58Decode(signerKey.slice(9));
2417
+ if (!decoded || decoded.length !== 35) return false;
2418
+ if (decoded[0] !== P256_PUBKEY_MULTICODEC[0] || decoded[1] !== P256_PUBKEY_MULTICODEC[1]) return false;
2419
+ const parityPrefix = decoded[2];
2420
+ if (parityPrefix !== 2 && parityPrefix !== 3) return false;
2421
+ const didX = decoded.subarray(3, 35);
2422
+ const jwkX = base64UrlToBytes(creatorKey.x);
2423
+ const jwkY = base64UrlToBytes(creatorKey.y);
2424
+ if (jwkX.length !== 32 || jwkY.length !== 32) return false;
2425
+ if (!bytesEqual(didX, jwkX)) return false;
2426
+ return (jwkY[31] & 1) === 1 === (parityPrefix === 3);
2427
+ }
2428
+ /**
2429
+ * Sets the initial policy. Valid only while the auth scope is uninitialized
2430
+ * (version 0). The input version is the policy language version and must be an
2431
+ * integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
2432
+ * document it must be signed by the document creator (`header.sig.publicKey`).
2433
+ * A creator-less policy must include a grant permitting execute on the auth
2434
+ * scope, or it would be born locked out.
2435
+ */
2436
+ function applyInitializeAuthAction(document, action) {
2437
+ assertActionInputShape(action.input);
2438
+ const { version, grants } = action.input;
2439
+ if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
2440
+ if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
2441
+ if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
2442
+ const creatorKey = document.header.sig.publicKey;
2443
+ const signerKey = action.context?.signer?.app.key;
2444
+ const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
2445
+ if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
2446
+ const creator = hasCreator ? signerKey : void 0;
2447
+ assertValidInitialGrants(grants, document.header.documentType, creator);
2448
+ return {
2449
+ ...document,
2450
+ state: {
2451
+ ...document.state,
2452
+ auth: createAuthState(creator ? {
2453
+ version,
2454
+ grants,
2455
+ creator
2456
+ } : {
2457
+ version,
2458
+ grants
2459
+ })
2460
+ }
2461
+ };
2462
+ }
2463
+ /** Upserts a grant by id: replaces in place if present, otherwise appends. */
2464
+ function applySetGrantAction(document, action) {
2465
+ assertActionInputShape(action.input);
2466
+ const { grant } = action.input;
2467
+ const grants = document.state.auth.grants;
2468
+ assertValidGrantUpsert(grant, grants, document.header.documentType, document.state.auth.creator);
2469
+ return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
2470
+ }
2471
+ /**
2472
+ * Removes a grant by id; throws if the id is not present or if the removal
2473
+ * would leave a creator-less policy with no auth-administration grant.
2474
+ */
2475
+ function applyRemoveGrantAction(document, action) {
2476
+ assertActionInputShape(action.input);
2477
+ const { id } = action.input;
2478
+ const { grants, creator } = document.state.auth;
2479
+ if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
2480
+ const next = grants.filter((g) => g.id !== id);
2481
+ assertAuthAdministrationRetained(creator, grants, next, id);
2482
+ return withGrants(document, next);
2483
+ }
2484
+ /**
2485
+ * Moves a grant by id to a new index. Order is load-bearing (the last
2486
+ * applicable grant wins), so the relative order of the other grants is kept.
2487
+ * The target index is clamped to the valid range; an unknown id throws.
2488
+ *
2489
+ * Order alone decides which grant wins, so a move can take administration away
2490
+ * without changing the list's contents. It carries the same retention rule as
2491
+ * the two mutation paths.
2492
+ */
2493
+ function applyMoveGrantAction(document, action) {
2494
+ assertActionInputShape(action.input);
2495
+ const { id, index } = action.input;
2496
+ const { grants, creator } = document.state.auth;
2497
+ const from = grants.findIndex((g) => g.id === id);
2498
+ if (from === -1) throw new GrantNotFoundError(id);
2499
+ const next = [...grants];
2500
+ const [moved] = next.splice(from, 1);
2501
+ const to = Math.max(0, Math.min(index, next.length));
2502
+ next.splice(to, 0, moved);
2503
+ assertAuthAdministrationRetained(creator, grants, next, id);
2504
+ return withGrants(document, next);
2505
+ }
2506
+ /**
2507
+ * Dispatches an auth-scope action to its handler. This is the auth scope's
2508
+ * dedicated reducer: it is applied by the base reducer instead of the model
2509
+ * reducer, mirroring the document-scope platform handlers. Unknown types are a
2510
+ * no-op, matching the model-reducer default.
2511
+ */
2512
+ function applyAuthAction(document, action) {
2513
+ switch (action.type) {
2514
+ case "INITIALIZE_AUTH": return applyInitializeAuthAction(document, action);
2515
+ case "SET_GRANT": return applySetGrantAction(document, action);
2516
+ case "REMOVE_GRANT": return applyRemoveGrantAction(document, action);
2517
+ case "MOVE_GRANT": return applyMoveGrantAction(document, action);
2518
+ default: return document;
2519
+ }
2520
+ }
2521
+ /**
2522
+ * Because only creators can initialize auth scopes, we must verify that either
2523
+ * the document has no auth or the version and creator match.
2524
+ */
2525
+ function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
2526
+ if (!source || source.version === 0) return;
2527
+ if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
2528
+ }
2529
+ /**
2530
+ * The auth scope a state snapshot may install, given the policy already there.
2531
+ *
2532
+ * `applyAuthAction` is the validated door onto `state.auth`, but a whole-state
2533
+ * snapshot (UPGRADE_DOCUMENT's `initialState`, LOAD_STATE's `data`) replaces the
2534
+ * scope wholesale and is authorized as a `document`-scope write. Without this,
2535
+ * a subject holding `execute` on `document` and no auth grant at all can install
2536
+ * a policy of its choosing, name itself `creator` (which exempts the policy from
2537
+ * the retention rule for good), or wipe an existing policy by carrying the
2538
+ * default uninitialized one.
2539
+ *
2540
+ * Three cases:
2541
+ *
2542
+ * - the snapshot carries no policy, or an uninitialized one: the document
2543
+ * keeps the policy it has, so a default-state upgrade cannot reset it;
2544
+ * - the document is uninitialized and the snapshot carries a policy: the
2545
+ * policy is installed after the same validation genesis applies, so it
2546
+ * cannot be born locked out;
2547
+ * - both carry a policy: they must agree. A duplicate preserves its source's
2548
+ * policy (see {@link assertAuthPreservedOnDuplicate}), and anything else is
2549
+ * an attempt to replace one policy with another.
2550
+ */
2551
+ function resolveSnapshotAuth(documentId, documentType, current, incoming) {
2552
+ const currentAuth = current ?? createAuthState({
2553
+ version: 0,
2554
+ grants: []
2555
+ });
2556
+ if (!incoming || !incoming.version) return currentAuth;
2557
+ if (currentAuth.version !== 0) {
2558
+ if (stringify(incoming) !== stringify(currentAuth)) throw new AuthPolicyNotPreservedError(documentId);
2559
+ return incoming;
2560
+ }
2561
+ if (!Array.isArray(incoming.grants)) throw new InvalidActionInputError({ grants: "must be an array" });
2562
+ assertValidInitialGrants(incoming.grants, documentType, incoming.creator);
2563
+ return incoming;
2564
+ }
2565
+ /** UNDO, REDO and PRUNE are rejected on the auth scope. */
2566
+ function assertAuthScopeActionAllowed(action) {
2567
+ if (action.scope === "auth" && [
2568
+ "UNDO",
2569
+ "REDO",
2570
+ "PRUNE"
2571
+ ].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
2572
+ }
2573
+ /**
2574
+ * Evaluates the auth policy for a single request and reports why it refused.
2575
+ * Pure and deterministic.
2576
+ *
2577
+ * An uninitialized policy (version 0, absent auth state, or a legacy `{}`
2578
+ * auth scope serialized before PHAuthState had a version) leaves the document
2579
+ * open. Once a policy exists the default is deny, and grants stack in order.
2580
+ *
2581
+ * Group principals match only against a supplied groups map (the groups
2582
+ * projection, present when authGroups is on); with no map they never apply.
2583
+ * `where` clauses and { match } principals likewise evaluate only against a
2584
+ * supplied condition context (present when authConditions is on).
2585
+ */
2586
+ function evaluate(auth, subject, request, groups, conditions) {
2587
+ if (!auth || !auth.version) return { decision: "allow" };
2588
+ if (request.verb === "execute" && request.scope === "auth" && subject.key !== void 0 && subject.key === auth.creator) return { decision: "allow" };
2589
+ if (auth.version > 1) return {
2590
+ decision: "deny",
2591
+ refusal: "version-unsupported"
2592
+ };
2593
+ return evaluateGrantStack(auth.grants, subject, request, groups, conditions);
2594
+ }
2595
+ /**
2596
+ * Evaluates the auth policy for a single request. Pure and deterministic. This
2597
+ * is {@link evaluate} with the reason dropped.
2598
+ */
2599
+ function decide(auth, subject, request, groups, conditions) {
2600
+ return evaluate(auth, subject, request, groups, conditions).decision;
2601
+ }
2602
+ /**
2603
+ * The group document ids a single auth action's input names with `{ group }`
2604
+ * principals. INITIALIZE_AUTH contributes the groups named across its grants,
2605
+ * SET_GRANT the groups named by its one grant; REMOVE_GRANT and MOVE_GRANT
2606
+ * contribute nothing. Total over any input shape, because references are read
2607
+ * from the input as it arrived, including inputs later stored as errors.
2608
+ */
2609
+ function mentionedGroupIds(action) {
2610
+ const input = action.input;
2611
+ const candidates = [];
2612
+ if (action.type === "INITIALIZE_AUTH" && Array.isArray(input?.grants)) candidates.push(...input.grants);
2613
+ if (action.type === "SET_GRANT" && input?.grant !== void 0) candidates.push(input.grant);
2614
+ const ids = [];
2615
+ for (const candidate of candidates) {
2616
+ if (typeof candidate !== "object" || candidate === null) continue;
2617
+ const principal = candidate.principal;
2618
+ if (typeof principal !== "object" || principal === null) continue;
2619
+ const group = principal.group;
2620
+ if (typeof group === "string" && group !== "" && !ids.includes(group)) ids.push(group);
2621
+ }
2622
+ return ids;
2623
+ }
2624
+ //#endregion
2625
+ //#region document-model/denied.ts
2626
+ /**
2627
+ * True iff authorization rejected the action.
2628
+ */
2629
+ function isDenied(operation) {
2630
+ return operation.deniedReason !== void 0;
2631
+ }
2632
+ /**
2633
+ * The closed set of strings persisted as `deniedReason`. Re-evaluation compares
2634
+ * them, so they are consensus data: exact strings that embed no grant id,
2635
+ * subject or timestamp. Changing one is history-visible.
2636
+ */
2637
+ const DOCUMENT_DELETED_REASON = "document deleted";
2638
+ const AUTH_VERSION_UNSUPPORTED_REASON = "auth policy version unsupported";
2639
+ const AUTH_NO_GRANT_REASON = "no grant permits this operation";
2640
+ const AUTH_DENIED_BY_GRANT_REASON = "denied by grant";
1441
2641
  //#endregion
1442
2642
  //#region document-model/document-schema.ts
1443
2643
  const BaseDocumentHeaderSchema = z.object({
@@ -1710,6 +2910,7 @@ function createDocumentScopeOperations(header, state) {
1710
2910
  function baseCreateDocument(createState, initialState, documentType = "") {
1711
2911
  const state = createState(initialState);
1712
2912
  const header = createPresignedHeader(generateId(), documentType);
2913
+ header.protocolVersions = { "base-reducer": 2 };
1713
2914
  return {
1714
2915
  header,
1715
2916
  state,
@@ -1805,6 +3006,18 @@ function mapSkippedOperationsV2(operations) {
1805
3006
  * Uses the V2 model where consecutive NOOPs form chains.
1806
3007
  * Unlike V1 garbageCollect, this preserves ALL operations but marks which to apply.
1807
3008
  */
3009
+ /**
3010
+ * The base-reducer protocol version a document is written against. Every
3011
+ * document carries one, set from the CREATE_DOCUMENT input. A header without
3012
+ * one was built outside that path, and choosing a version on its behalf would
3013
+ * replay the document through a reducer it was not written for, so it is an
3014
+ * error rather than a default.
3015
+ */
3016
+ function baseReducerVersion(header) {
3017
+ const version = header.protocolVersions?.["base-reducer"];
3018
+ if (typeof version !== "number") throw new Error(`Document ${header.id} carries no base-reducer protocol version`);
3019
+ return version;
3020
+ }
1808
3021
  function garbageCollectV2(sortedOperations) {
1809
3022
  const result = [];
1810
3023
  let noopChainLength = 0;
@@ -1824,9 +3037,26 @@ function sortMappedOperations(operations) {
1824
3037
  const defaultCreateState = (state) => {
1825
3038
  return state;
1826
3039
  };
3040
+ /**
3041
+ * Records an operation in the history without applying it, which is what a
3042
+ * denied operation needs: it occupies its index and contributes no state.
3043
+ *
3044
+ * The scope defaults to the action's own, and is passed explicitly by a rebuild
3045
+ * that is walking one stream and does not want to trust the action's copy.
3046
+ */
3047
+ function appendWithoutApplying(document, operation, scope = operation.action.scope) {
3048
+ return {
3049
+ ...document,
3050
+ operations: {
3051
+ ...document.operations,
3052
+ [scope]: [...document.operations[scope] ?? [], operation]
3053
+ }
3054
+ };
3055
+ }
1827
3056
  function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
1828
3057
  const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
1829
- let documentState = initialState;
3058
+ const backfilledInitialState = backfillAuthState(initialState);
3059
+ let documentState = backfilledInitialState;
1830
3060
  const operationsToReplay = [];
1831
3061
  const allScopes = new Set([
1832
3062
  ...Object.keys(operations),
@@ -1861,12 +3091,13 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
1861
3091
  const document = {
1862
3092
  header,
1863
3093
  state: defaultCreateState(documentState),
1864
- initialState,
3094
+ initialState: backfilledInitialState,
1865
3095
  operations: initialOperations,
1866
3096
  clipboard: []
1867
3097
  };
1868
3098
  let result = document;
1869
3099
  if (operationsToReplay.length) result = operationsToReplay.reduce((document, operation) => {
3100
+ if (isDenied(operation)) return updateHeaderRevision(appendWithoutApplying(document, operation), operation.action.scope, operation.timestampUtcMs);
1870
3101
  return reducer(document, operation.action, dispatch, {
1871
3102
  ignoreSkipOperations: true,
1872
3103
  checkHashes,
@@ -2390,14 +3621,31 @@ function redoOperation(document, action, skip) {
2390
3621
  });
2391
3622
  }
2392
3623
  function loadStateOperation(document, action) {
3624
+ const loaded = backfillAuthState(action.state.data);
3625
+ loaded.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, loaded.auth);
2393
3626
  return {
2394
3627
  ...document,
2395
3628
  header: {
2396
3629
  ...document.header,
2397
3630
  name: action.state.name
2398
3631
  },
2399
- state: action.state.data
3632
+ state: loaded
3633
+ };
3634
+ }
3635
+ /**
3636
+ * Reads an operation's outcome. A denial takes precedence over a reducer
3637
+ * error, since a denied operation never reaches its reducer.
3638
+ */
3639
+ function operationOutcome(operation) {
3640
+ if (operation.deniedReason !== void 0) return {
3641
+ kind: "denied",
3642
+ reason: operation.deniedReason
3643
+ };
3644
+ if (operation.error !== void 0) return {
3645
+ kind: "reducer-error",
3646
+ message: operation.error
2400
3647
  };
3648
+ return { kind: "applied" };
2401
3649
  }
2402
3650
  //#endregion
2403
3651
  //#region document-model/reducer.ts
@@ -2572,12 +3820,13 @@ function processUndoOperation(document, scope, customReducer, reuseOperationResu
2572
3820
  function baseReducer(document, action, customReducer, dispatch, options = {}) {
2573
3821
  const { skip, ignoreSkipOperations = false, reuseOperationResultingState = false, operationResultingStateParser, pruneOnSkip = true, branch = "main" } = options;
2574
3822
  let _action = actionFromAction(action);
3823
+ assertAuthScopeActionAllowed(_action);
2575
3824
  let skipValue = skip ?? options.replayOptions?.operation.skip ?? 0;
2576
3825
  let newDocument = { ...document };
2577
3826
  let reuseLastOperationIndex = false;
2578
3827
  const shouldProcessSkipOperation = !ignoreSkipOperations && skipValue > 0;
2579
3828
  if (isUndoRedo(_action)) {
2580
- const { skip: calculatedSkip, action: transformedAction, document: processedDocument, reuseLastOperationIndex: reuseIndex } = processUndoRedo(document, _action, skipValue, options.protocolVersion ?? 1);
3829
+ const { skip: calculatedSkip, action: transformedAction, document: processedDocument, reuseLastOperationIndex: reuseIndex } = processUndoRedo(document, _action, skipValue, options.protocolVersion ?? baseReducerVersion(document.header));
2581
3830
  _action = transformedAction;
2582
3831
  skipValue = calculatedSkip;
2583
3832
  newDocument = processedDocument;
@@ -2593,7 +3842,7 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
2593
3842
  branch
2594
3843
  };
2595
3844
  newDocument = updateDocument(newDocument, _action, reuseLastOperationIndex, skipValue, operationContext, options.replayOptions?.operation, options.skipIndexValidation);
2596
- const protocolVersion = options.protocolVersion ?? 1;
3845
+ const protocolVersion = options.protocolVersion ?? baseReducerVersion(document.header);
2597
3846
  if (isUndo(action) && protocolVersion < 2) return processUndoOperation(newDocument, action.scope, customReducer);
2598
3847
  const isNoopWithSkip = _action.type === "NOOP" && skipValue > 0;
2599
3848
  if ((isUndo(action) || isNoopWithSkip) && protocolVersion >= 2) {
@@ -2619,6 +3868,13 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
2619
3868
  }
2620
3869
  newDocument = create(newDocument, (draft) => {
2621
3870
  try {
3871
+ if (_action.scope === "auth") {
3872
+ const authState = applyAuthAction(newDocument, _action).state;
3873
+ unsafe(() => {
3874
+ draft.state = castDraft(authState);
3875
+ });
3876
+ return;
3877
+ }
2622
3878
  const newState = customReducer(draft.state, _action, dispatch);
2623
3879
  if (newState) unsafe(() => {
2624
3880
  draft.state = castDraft(newState);
@@ -2648,8 +3904,8 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
2648
3904
  "PRUNE"
2649
3905
  ].includes(_action.type)) return newDocument;
2650
3906
  const scope = _action.scope || "global";
2651
- let hash = hashDocumentStateForScope(newDocument, scope);
2652
- if (options.replayOptions?.operation.hash && options.replayOptions.operation.hash !== "") hash = options.replayOptions.operation.hash;
3907
+ const replayHash = options.replayOptions?.operation.hash;
3908
+ const hash = replayHash ? replayHash : hashDocumentStateForScope(newDocument, scope);
2653
3909
  const lastOperation = newDocument.operations[scope]?.at(-1);
2654
3910
  if (lastOperation) {
2655
3911
  lastOperation.hash = hash;
@@ -3414,14 +4670,27 @@ const documentModelStateReducer = (state, action) => {
3414
4670
  const documentModelReducer = createReducer(documentModelStateReducer);
3415
4671
  //#endregion
3416
4672
  //#region document-model/upgrades.ts
4673
+ /**
4674
+ * Canonical document-model version normalization: documents stamped with 0
4675
+ * or nothing at all predate versioning and are treated as version 1, the
4676
+ * same version the registry assigns unversioned modules. Every consumer
4677
+ * that resolves a module or compares versions must use this rule; resolving
4678
+ * 0 to "latest" instead re-pins a legacy document's history to whichever
4679
+ * module happens to be newest.
4680
+ */
4681
+ function normalizeDocumentModelVersion(version) {
4682
+ return version && version > 0 ? version : 1;
4683
+ }
3417
4684
  function applyInitialState(document, action) {
3418
4685
  const input = action.input;
3419
4686
  const newState = input.initialState || input.state;
3420
4687
  if (newState) {
3421
- document.state = {
4688
+ const merged = backfillAuthState({
3422
4689
  ...document.state,
3423
4690
  ...newState
3424
- };
4691
+ });
4692
+ merged.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, merged.auth);
4693
+ document.state = merged;
3425
4694
  document.initialState = document.state;
3426
4695
  }
3427
4696
  }
@@ -3483,7 +4752,6 @@ function computeUpgradeTransitions(manifest, fromVersion, toVersion) {
3483
4752
  }
3484
4753
  //#endregion
3485
4754
  //#region document-model/versioned-replay.ts
3486
- const NON_DOMAIN_SCOPES$1 = new Set(["auth", "document"]);
3487
4755
  function highestReducerVersion(reducers) {
3488
4756
  const keys = Object.keys(reducers).map(Number);
3489
4757
  if (keys.length === 0) throw new Error("VersionedReplayConfig.reducers must not be empty");
@@ -3511,15 +4779,15 @@ function highestReducerVersion(reducers) {
3511
4779
  */
3512
4780
  function replayDocumentVersioned(initialState, operations, config, header, dispatch, options) {
3513
4781
  const { checkHashes = true, skipIndexValidation } = options || {};
3514
- const protocolVersion = header.protocolVersions?.["base-reducer"] ?? 1;
4782
+ const protocolVersion = baseReducerVersion(header);
3515
4783
  const spine = (operations["document"] ?? []).slice().sort((a, b) => a.index - b.index);
3516
4784
  const upgrades = spine.filter((op) => op.action.type === "UPGRADE_DOCUMENT");
3517
4785
  const legacyFallback = () => {
3518
- const domainOps = Object.fromEntries(Object.entries(operations).filter(([s]) => !NON_DOMAIN_SCOPES$1.has(s)));
4786
+ const replayOps = Object.fromEntries(Object.entries(operations).filter(([s]) => s !== "document"));
3519
4787
  const latestVersion = highestReducerVersion(config.reducers);
3520
4788
  const reducer = config.reducers[latestVersion];
3521
4789
  return {
3522
- ...replayDocument(initialState, domainOps, reducer, header, dispatch, {}, options),
4790
+ ...replayDocument(initialState, replayOps, reducer, header, dispatch, {}, options),
3523
4791
  operations
3524
4792
  };
3525
4793
  };
@@ -3543,14 +4811,14 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3543
4811
  const a = op.action;
3544
4812
  return a.input.fromVersion > 0 && a.input.fromVersion < a.input.toVersion;
3545
4813
  });
3546
- const domainScopes = Object.keys(operations).filter((s) => !NON_DOMAIN_SCOPES$1.has(s));
4814
+ const replayScopes = Object.keys(operations).filter((s) => s !== "document");
3547
4815
  const scopeOps = {};
3548
- for (const s of domainScopes) scopeOps[s] = (operations[s] ?? []).slice().sort((a, b) => a.index - b.index);
4816
+ for (const s of replayScopes) scopeOps[s] = (operations[s] ?? []).slice().sort((a, b) => a.index - b.index);
3549
4817
  const boundaries = validatedUpgrades.map((upgradeOp) => {
3550
4818
  const revisionSnapshot = upgradeOp.action.input.revision;
3551
4819
  const upgradeTimestamp = upgradeOp.timestampUtcMs;
3552
4820
  const boundary = {};
3553
- for (const s of domainScopes) {
4821
+ for (const s of replayScopes) {
3554
4822
  const ops = scopeOps[s] ?? [];
3555
4823
  if (revisionSnapshot !== void 0) {
3556
4824
  const rev = revisionSnapshot[s] ?? 0;
@@ -3568,7 +4836,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3568
4836
  }
3569
4837
  return boundary;
3570
4838
  });
3571
- for (let i = 1; i < boundaries.length; i++) for (const s of domainScopes) {
4839
+ for (let i = 1; i < boundaries.length; i++) for (const s of replayScopes) {
3572
4840
  const prev = boundaries[i - 1]?.[s] ?? 0;
3573
4841
  const curr = boundaries[i]?.[s] ?? 0;
3574
4842
  if (boundaries[i]) boundaries[i][s] = Math.max(prev, curr);
@@ -3580,10 +4848,11 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3580
4848
  ]);
3581
4849
  const initialOperations = {};
3582
4850
  for (const s of allScopes) initialOperations[s] = [];
4851
+ const backfilledSeed = backfillAuthState(seedState);
3583
4852
  let document = {
3584
4853
  header,
3585
- state: seedState,
3586
- initialState: seedState,
4854
+ state: backfilledSeed,
4855
+ initialState: backfilledSeed,
3587
4856
  operations: initialOperations,
3588
4857
  clipboard: []
3589
4858
  };
@@ -3591,17 +4860,15 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3591
4860
  const segmentEndHashPerScope = /* @__PURE__ */ new Map();
3592
4861
  for (let k = 0; k <= validatedUpgrades.length; k++) {
3593
4862
  const reducer = config.reducers[currentVersion];
3594
- if (!reducer) {
3595
- const available = Object.keys(config.reducers).join(", ");
3596
- throw new Error(`No reducer registered for document version ${currentVersion}. Available versions: ${available}`);
3597
- }
3598
- for (const s of domainScopes) {
4863
+ if (!reducer) throw new UnsupportedDocumentModelVersionError(header.documentType, currentVersion, Object.keys(config.reducers).map(Number).sort((a, b) => a - b));
4864
+ for (const s of replayScopes) {
3599
4865
  const ops = scopeOps[s] ?? [];
3600
4866
  const segStart = k === 0 ? 0 : boundaries[k - 1]?.[s] ?? 0;
3601
4867
  const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
3602
4868
  const segOps = ops.slice(segStart, segEnd);
3603
4869
  for (const op of segOps) {
3604
- document = reducer(document, op.action, dispatch, {
4870
+ if (isDenied(op)) document = updateHeaderRevision(appendWithoutApplying(document, op, s), s, op.timestampUtcMs);
4871
+ else document = reducer(document, op.action, dispatch, {
3605
4872
  ignoreSkipOperations: true,
3606
4873
  checkHashes,
3607
4874
  skipIndexValidation,
@@ -3618,6 +4885,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3618
4885
  if (!spineOp) continue;
3619
4886
  const spineActionType = spineOp.action.type;
3620
4887
  if (spineActionType === "CREATE_DOCUMENT" || spineActionType === "UPGRADE_DOCUMENT") continue;
4888
+ if (isDenied(spineOp)) continue;
3621
4889
  if (spineActionType === "DELETE_DOCUMENT") document = applyDeleteDocumentAction(document, spineOp.action);
3622
4890
  else document = reducer(document, spineOp.action, dispatch, {
3623
4891
  ignoreSkipOperations: true,
@@ -3648,7 +4916,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3648
4916
  }
3649
4917
  };
3650
4918
  if (!checkHashes) {
3651
- const allReplayedOps = domainScopes.flatMap((s) => scopeOps[s] ?? []);
4919
+ const allReplayedOps = replayScopes.flatMap((s) => scopeOps[s] ?? []);
3652
4920
  for (const scope of Object.keys(document.state)) {
3653
4921
  const capturedHash = segmentEndHashPerScope.get(scope);
3654
4922
  const scopeHash = capturedHash !== void 0 ? capturedHash : hashDocumentStateForScope(document, scope);
@@ -3692,7 +4960,6 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
3692
4960
  }
3693
4961
  //#endregion
3694
4962
  //#region document-model/files.ts
3695
- const NON_DOMAIN_SCOPES = new Set(["auth", "document"]);
3696
4963
  function zipAsync(data) {
3697
4964
  return new Promise((resolve, reject) => {
3698
4965
  zip(data, (err, out) => err ? reject(err) : resolve(out));
@@ -3799,7 +5066,7 @@ async function parseZipData(data) {
3799
5066
  async function loadFromZipData(data, reducer, options) {
3800
5067
  const { initialState, header, clearedOperations } = await parseZipData(data);
3801
5068
  return {
3802
- ...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) => !NON_DOMAIN_SCOPES.has(scope))), reducer, header, void 0, {}, options),
5069
+ ...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) => scope !== "document")), reducer, header, void 0, {}, options),
3803
5070
  operations: clearedOperations
3804
5071
  };
3805
5072
  }
@@ -3816,6 +5083,42 @@ async function baseLoadFromInput(input, reducer, options) {
3816
5083
  async function baseLoadFromInputVersioned(input, config, options) {
3817
5084
  return loadFromZipDataVersioned(await toUint8Array(input), config, options);
3818
5085
  }
5086
+ /**
5087
+ * Whether this zip is a single Powerhouse document: the document's four JSON
5088
+ * entries (header/state/current-state/operations) at the archive root. A
5089
+ * bulk archive has a folder tree instead. Returns false for any input that
5090
+ * is not a readable zip.
5091
+ */
5092
+ async function isDocumentZip(data) {
5093
+ let files;
5094
+ try {
5095
+ files = await unzipAsync(data);
5096
+ } catch {
5097
+ return false;
5098
+ }
5099
+ return Boolean(files["header.json"]) && Boolean(files["state.json"]) && Boolean(files["operations.json"]);
5100
+ }
5101
+ /**
5102
+ * The file entries of a zip (directory entries excluded). Used for bulk
5103
+ * archives; throws when the archive holds no files. Note this does NOT
5104
+ * validate that the entries are document zips — pair with isDocumentZip.
5105
+ */
5106
+ async function parseBulkArchive(data) {
5107
+ const files = await unzipAsync(data);
5108
+ const entries = Object.entries(files).filter(([name]) => !name.endsWith("/")).map(([path, value]) => ({
5109
+ path,
5110
+ data: value
5111
+ }));
5112
+ if (entries.length === 0) throw new Error("Archive contains no files");
5113
+ return entries;
5114
+ }
5115
+ /**
5116
+ * Assemble a zip from raw entries. A key ending in "/" with empty data is a
5117
+ * directory entry, so an archive's folder structure survives a round-trip.
5118
+ */
5119
+ async function zipEntries(entries) {
5120
+ return zipAsync(entries);
5121
+ }
3819
5122
  const documentModelLoadFromInput = (input) => {
3820
5123
  return baseLoadFromInput(input, documentModelReducer);
3821
5124
  };
@@ -3835,105 +5138,6 @@ const getFileBrowser = (file) => {
3835
5138
  return Promise.resolve().then(() => readFileBrowser(file));
3836
5139
  };
3837
5140
  //#endregion
3838
- //#region document-model/state.ts
3839
- /**
3840
- * Creates a default PHAuthState
3841
- */
3842
- function defaultAuthState() {
3843
- return {};
3844
- }
3845
- /**
3846
- * Creates a default PHDocumentState
3847
- */
3848
- function defaultDocumentState() {
3849
- return {
3850
- version: 0,
3851
- hash: {
3852
- algorithm: HASH_ALGORITHM_SHA1,
3853
- encoding: HASH_ENCODING_BASE64
3854
- }
3855
- };
3856
- }
3857
- /**
3858
- * Creates a default PHBaseState with auth and document properties
3859
- */
3860
- function defaultBaseState() {
3861
- return {
3862
- auth: defaultAuthState(),
3863
- document: defaultDocumentState()
3864
- };
3865
- }
3866
- /**
3867
- * Creates a PHAuthState with the given properties
3868
- */
3869
- function createAuthState(auth) {
3870
- return {
3871
- ...defaultAuthState(),
3872
- ...auth
3873
- };
3874
- }
3875
- /**
3876
- * Creates a PHDocumentState with the given properties
3877
- */
3878
- function createDocumentState(document) {
3879
- return {
3880
- ...defaultDocumentState(),
3881
- ...document
3882
- };
3883
- }
3884
- /**
3885
- * Creates a PHBaseState with the given auth and document properties
3886
- */
3887
- function createBaseState(auth, document) {
3888
- return {
3889
- auth: createAuthState(auth),
3890
- document: createDocumentState(document)
3891
- };
3892
- }
3893
- function defaultGlobalState() {
3894
- return {
3895
- ...defaultBaseState(),
3896
- author: {
3897
- name: "",
3898
- website: ""
3899
- },
3900
- description: "",
3901
- extension: "",
3902
- id: "",
3903
- name: "",
3904
- specifications: []
3905
- };
3906
- }
3907
- function defaultLocalState() {
3908
- return {};
3909
- }
3910
- function defaultPHState() {
3911
- return {
3912
- ...defaultBaseState(),
3913
- global: defaultGlobalState(),
3914
- local: defaultLocalState()
3915
- };
3916
- }
3917
- function createGlobalState(state) {
3918
- return {
3919
- ...defaultGlobalState(),
3920
- ...state || {}
3921
- };
3922
- }
3923
- function createLocalState(state) {
3924
- return {
3925
- ...defaultLocalState(),
3926
- ...state || {}
3927
- };
3928
- }
3929
- function createState(baseState, globalState, localState) {
3930
- return {
3931
- ...createBaseState(baseState?.auth, baseState?.document),
3932
- global: createGlobalState(globalState),
3933
- local: createLocalState(localState)
3934
- };
3935
- }
3936
- //#endregion
3937
- export { AddChangeLogItemInputSchema, AddModuleInputSchema, AddOperationErrorInputSchema, AddOperationExampleInputSchema, AddOperationInputSchema, AddStateExampleInputSchema, AuthorSchema, BaseDocumentHeaderSchema, BaseDocumentStateSchema, CodeExampleSchema, ConfigEntrySchema, ConfigEntryTypeSchema, DeleteChangeLogItemInputSchema, DeleteModuleInputSchema, DeleteOperationErrorInputSchema, DeleteOperationExampleInputSchema, DeleteOperationInputSchema, DeleteStateExampleInputSchema, DocumentActionSchema, DocumentModelGlobalStateSchema, DocumentModelHeaderSchema, DocumentModelInputSchema, DocumentModelPHStateSchema, DocumentModelSchema, DocumentSpecificationSchema, DowngradeNotSupportedError, FileSystemError, HASH_ALGORITHM_SHA1, HASH_ALGORITHM_SHA256, HASH_ALGORITHM_SHA512, HASH_ENCODING_BASE64, HASH_ENCODING_HEX, HashMismatchError, IntegrityIssueSubType, IntegrityIssueType, InvalidActionInputError, InvalidActionInputZodError, LoadStateActionInputSchema, LoadStateActionSchema, LoadStateActionStateInputSchema, Load_StateSchema, ManifestSchema, ModuleSchema, MoveOperationInputSchema, OPERATION_NAME_PATTERN, OperationErrorSchema, OperationScopeSchema, OperationSpecificationSchema, PowerhouseModuleSchema, PowerhouseModulesSchema, PruneActionInputSchema, PruneActionSchema, PruneSchema, PublisherSchema, RESERVED_OPERATION_NAMES, RedoActionInputSchema, RedoActionSchema, RedoSchema, ReorderChangeLogItemsInputSchema, ReorderModuleOperationsInputSchema, ReorderModulesInputSchema, ReorderOperationErrorsInputSchema, ReorderOperationExamplesInputSchema, ReorderStateExamplesInputSchema, ScopeStateSchema, SetAuthorNameInputSchema, SetAuthorWebsiteInputSchema, SetInitialStateInputSchema, SetModelDescriptionInputSchema, SetModelExtensionInputSchema, SetModelIdInputSchema, SetModelNameInputSchema, SetModuleDescriptionInputSchema, SetModuleNameInputSchema, SetNameActionInputSchema, SetNameActionSchema, SetOperationDescriptionInputSchema, SetOperationErrorCodeInputSchema, SetOperationErrorDescriptionInputSchema, SetOperationErrorNameInputSchema, SetOperationErrorTemplateInputSchema, SetOperationNameInputSchema, SetOperationReducerInputSchema, SetOperationSchemaInputSchema, SetOperationScopeInputSchema, SetOperationTemplateInputSchema, SetPreferredEditorActionInputSchema, SetPreferredEditorActionSchema, SetStateSchemaInputSchema, Set_NameSchema, Set_PreferredEditorSchema, StateSchema, UndoActionInputSchema, UndoActionSchema, UndoSchema, UpdateChangeLogItemInputSchema, UpdateOperationExampleInputSchema, UpdateStateExampleInputSchema, ab2hex, actionContext, actionFromAction, actionSigner, actions, addChangeLogItem, addModule, addOperation, addOperationError, addOperationExample, addStateExample, addUndo, applyDeleteDocumentAction, applyUpgradeDocumentAction, assertIsDocumentModelDocument, assertIsDocumentModelState, assertModuleIdUnique, assertOperationErrorIdUnique, assertOperationExampleIdUnique, assertOperationIdUnique, attachBranch, baseActions, baseCreateDocument, baseLoadFromInput, baseLoadFromInputVersioned, baseReducer, baseSaveToFileHandle, buildOperationSignature, buildOperationSignatureMessage, buildOperationSignatureParams, buildSignedAction, checkCleanedOperationsIntegrity, checkOperationsIntegrity, computeUpgradeTransitions, createAction, createAuthState, createBaseState, createDocumentState, createGlobalState, createLocalState, createMinimalZip, createPresignedHeader, createReducer, createSignedHeader, createSignedHeaderForSigner, createState, createVerificationSigner, createZip, defaultAuthState, defaultBaseState, defaultDocumentState, defaultGlobalState, defaultLocalState, defaultPHState, definedNonNullAnySchema, deleteChangeLogItem, deleteModule, deleteOperation, deleteOperationError, deleteOperationExample, deleteStateExample, deriveOperationId, diffOperations, documentModelActions, documentModelDocumentType, documentModelFileExtension, documentModelGlobalState, documentModelHeaderReducer, documentModelInitialGlobalState, documentModelInitialLocalState, documentModelLoadFromInput, documentModelModuleReducer, documentModelOperationErrorReducer, documentModelOperationExampleReducer, documentModelOperationReducer, documentModelReducer, documentModelSaveToFileHandle, documentModelStateReducer, documentModelStateSchemaReducer, documentModelVersioningReducer, fetchFileBrowser, filterDocumentOperationsResultingState, filterDuplicatedOperations, findModuleOrThrow, findOperationErrorOrThrow, findOperationExampleOrThrow, findOperationOrThrow, garbageCollect, garbageCollectDocumentOperations, garbageCollectV2, generateId, generateMock, getAllOperationNames, getDocumentLastModified, getFileBrowser, getUnixTimestamp, groupOperationsByScope, hashBrowser, hashDocumentStateForScope, hex2ab, isDefinedNonNullAny, isDocumentAction, isDocumentModelDocument, isDocumentModelState, isNoopOperation, isReservedOperationName, isUndo, isUndoRedo, isValidOperationNameFormat, loadState, loadStateOperation, mapSkippedOperations, mapSkippedOperationsV2, merge, moveOperation, nextSkipNumber, noop, operationExampleCreators, operationFromAction, operationFromOperation, operationWithContext, operationsAreEqual, parseResultingState, precedes, prepareOperations, processUndoRedo, prune, pruneOperation, readFileBrowser, readOnly, redo, redoOperation, releaseNewVersion, removeExistingOperations, reorderChangeLogItems, reorderModuleOperations, reorderModules, reorderOperationErrors, reorderOperationExamples, reorderStateExamples, replayDocument, replayDocumentVersioned, replayOperations, reshuffleByTimestamp, reshuffleByTimestampAndIndex, setAuthorName, setAuthorWebsite, setInitialState, setModelDescription, setModelExtension, setModelId, setModelName, setModuleDescription, setModuleName, setName, setNameOperation, setOperationDescription, setOperationErrorCode, setOperationErrorDescription, setOperationErrorName, setOperationErrorTemplate, setOperationName, setOperationReducer, setOperationSchema, setOperationScope, setOperationTemplate, setPreferredEditor, setPreferredEditorOperation, setStateSchema, sign, skipHeaderOperations, sortMappedOperations, sortOperations, split, undo, undoOperation, undoOperationV2, updateChangeLogItem, updateDocument, updateHeaderRevision, updateOperationExample, updateStateExample, validateHeader, validateInitialState, validateModule, validateModuleOperation, validateModules, validateOperationName, validateOperations, validateStateSchemaName, verify, verifyOperationSignature, writeFileBrowser };
5141
+ export { AUTH_ACTION_TYPES, AUTH_DENIED_BY_GRANT_REASON, AUTH_NO_GRANT_REASON, AUTH_VERSION_UNSUPPORTED_REASON, AddChangeLogItemInputSchema, AddModuleInputSchema, AddOperationErrorInputSchema, AddOperationExampleInputSchema, AddOperationInputSchema, AddStateExampleInputSchema, AuthActionNotAllowedError, AuthAdministrationLockoutError, AuthAdministrationMissingError, AuthAlreadyInitializedError, AuthInitializerNotCreatorError, AuthPolicyNotPreservedError, AuthorSchema, BaseDocumentHeaderSchema, BaseDocumentStateSchema, CodeExampleSchema, ConfigEntrySchema, ConfigEntryTypeSchema, DOCUMENT_DELETED_REASON, DeleteChangeLogItemInputSchema, DeleteModuleInputSchema, DeleteOperationErrorInputSchema, DeleteOperationExampleInputSchema, DeleteOperationInputSchema, DeleteStateExampleInputSchema, DocumentActionSchema, DocumentModelGlobalStateSchema, DocumentModelHeaderSchema, DocumentModelInputSchema, DocumentModelPHStateSchema, DocumentModelSchema, DocumentSpecificationSchema, DowngradeNotSupportedError, FileSystemError, GrantNotFoundError, GrantSchema, GroupPrincipalNotAllowedError, HASH_ALGORITHM_SHA1, HASH_ALGORITHM_SHA256, HASH_ALGORITHM_SHA512, HASH_ENCODING_BASE64, HASH_ENCODING_HEX, HashMismatchError, InitializeAuthActionInputSchema, IntegrityIssueSubType, IntegrityIssueType, InvalidActionInputError, InvalidActionInputZodError, InvalidAuthVersionError, InvalidGrantError, LoadStateActionInputSchema, LoadStateActionSchema, LoadStateActionStateInputSchema, Load_StateSchema, MAX_AUTH_GRANTS, MAX_CAPABILITY_OPERATIONS, MAX_CONDITION_DEPTH, MAX_CONDITION_NODES, MAX_SUPPORTED_AUTH_VERSION, ManifestSchema, ModuleSchema, MoveGrantActionInputSchema, MoveOperationInputSchema, OPERATION_NAME_PATTERN, OperationErrorSchema, OperationScopeSchema, OperationSpecificationSchema, PowerhouseModuleSchema, PowerhouseModulesSchema, PruneActionInputSchema, PruneActionSchema, PruneSchema, PublisherSchema, PwaConfigSchema, RESERVED_OPERATION_NAMES, RedoActionInputSchema, RedoActionSchema, RedoSchema, RemoveGrantActionInputSchema, ReorderChangeLogItemsInputSchema, ReorderModuleOperationsInputSchema, ReorderModulesInputSchema, ReorderOperationErrorsInputSchema, ReorderOperationExamplesInputSchema, ReorderStateExamplesInputSchema, ScopeStateSchema, SetAuthorNameInputSchema, SetAuthorWebsiteInputSchema, SetGrantActionInputSchema, SetInitialStateInputSchema, SetModelDescriptionInputSchema, SetModelExtensionInputSchema, SetModelIdInputSchema, SetModelNameInputSchema, SetModuleDescriptionInputSchema, SetModuleNameInputSchema, SetNameActionInputSchema, SetNameActionSchema, SetOperationDescriptionInputSchema, SetOperationErrorCodeInputSchema, SetOperationErrorDescriptionInputSchema, SetOperationErrorNameInputSchema, SetOperationErrorTemplateInputSchema, SetOperationNameInputSchema, SetOperationReducerInputSchema, SetOperationSchemaInputSchema, SetOperationScopeInputSchema, SetOperationTemplateInputSchema, SetPreferredEditorActionInputSchema, SetPreferredEditorActionSchema, SetStateSchemaInputSchema, Set_NameSchema, Set_PreferredEditorSchema, StateSchema, UndoActionInputSchema, UndoActionSchema, UndoSchema, UnsupportedDocumentModelVersionError, UpdateChangeLogItemInputSchema, UpdateOperationExampleInputSchema, UpdateStateExampleInputSchema, ab2hex, actionContext, actionFromAction, actionSigner, actions, addChangeLogItem, addModule, addOperation, addOperationError, addOperationExample, addStateExample, addUndo, appendWithoutApplying, applyAuthAction, applyDeleteDocumentAction, applyInitializeAuthAction, applyMoveGrantAction, applyRemoveGrantAction, applySetGrantAction, applyUpgradeDocumentAction, assertAuthAdministrationRetained, assertAuthPreservedOnDuplicate, assertAuthScopeActionAllowed, assertIsDocumentModelDocument, assertIsDocumentModelState, assertModuleIdUnique, assertOperationErrorIdUnique, assertOperationExampleIdUnique, assertOperationIdUnique, assertValidGrant, assertValidGrantUpsert, assertValidInitialGrants, attachBranch, backfillAuthState, base58Decode, base64UrlToBytes, baseActions, baseCreateDocument, baseLoadFromInput, baseLoadFromInputVersioned, baseReducer, baseReducerVersion, baseSaveToFileHandle, buildOperationSignature, buildOperationSignatureMessage, buildOperationSignatureParams, buildSignedAction, checkCleanedOperationsIntegrity, checkOperationsIntegrity, computeUpgradeTransitions, createAction, createAuthState, createBaseState, createDocumentState, createGlobalState, createLocalState, createMinimalZip, createPresignedHeader, createReducer, createSignedHeader, createSignedHeaderForSigner, createState, createVerificationSigner, createZip, decide, defaultAuthState, defaultBaseState, defaultDocumentState, defaultGlobalState, defaultLocalState, defaultPHState, definedNonNullAnySchema, deleteChangeLogItem, deleteModule, deleteOperation, deleteOperationError, deleteOperationExample, deleteStateExample, deriveOperationId, deserializeSignature, diffOperations, documentModelActions, documentModelDocumentType, documentModelFileExtension, documentModelGlobalState, documentModelHeaderReducer, documentModelInitialGlobalState, documentModelInitialLocalState, documentModelLoadFromInput, documentModelModuleReducer, documentModelOperationErrorReducer, documentModelOperationExampleReducer, documentModelOperationReducer, documentModelReducer, documentModelSaveToFileHandle, documentModelStateReducer, documentModelStateSchemaReducer, documentModelVersioningReducer, evaluate, evaluateCondition, evaluateGrantStack, evaluateGrants, fetchFileBrowser, filterDocumentOperationsResultingState, filterDuplicatedOperations, findModuleOrThrow, findOperationErrorOrThrow, findOperationExampleOrThrow, findOperationOrThrow, garbageCollect, garbageCollectDocumentOperations, garbageCollectV2, generateId, generateMock, getAllOperationNames, getDocumentLastModified, getFileBrowser, getUnixTimestamp, grantProblem, groupDocumentType, groupMembershipActionTypes, groupOperationsByScope, hashBrowser, hashDocumentStateForScope, hex2ab, initializeAuth, isAuthAction, isDefinedNonNullAny, isDenied, isDocumentAction, isDocumentCreator, isDocumentModelDocument, isDocumentModelState, isDocumentZip, isNoopOperation, isPlainValue, isReservedOperationName, isUndo, isUndoRedo, isValidOperationNameFormat, loadState, loadStateOperation, mapSkippedOperations, mapSkippedOperationsV2, mentionedGroupIds, merge, moveGrant, moveOperation, nextSkipNumber, noop, normalizeDocumentModelVersion, operationExampleCreators, operationFromAction, operationFromOperation, operationOutcome, operationWithContext, operationsAreEqual, parseBulkArchive, parseResultingState, precedes, prepareOperations, processUndoRedo, prune, pruneOperation, readFileBrowser, readOnly, redo, redoOperation, referencedGroupIds, releaseNewVersion, removeExistingOperations, removeGrant, reorderChangeLogItems, reorderModuleOperations, reorderModules, reorderOperationErrors, reorderOperationExamples, reorderStateExamples, replayDocument, replayDocumentVersioned, replayOperations, reshuffleByTimestamp, reshuffleByTimestampAndIndex, resolveSnapshotAuth, serializeSignature, setAuthorName, setAuthorWebsite, setGrant, setInitialState, setModelDescription, setModelExtension, setModelId, setModelName, setModuleDescription, setModuleName, setName, setNameOperation, setOperationDescription, setOperationErrorCode, setOperationErrorDescription, setOperationErrorName, setOperationErrorTemplate, setOperationName, setOperationReducer, setOperationSchema, setOperationScope, setOperationTemplate, setPreferredEditor, setPreferredEditorOperation, setStateSchema, sign, skipHeaderOperations, sortMappedOperations, sortOperations, split, toTransportAction, undo, undoOperation, undoOperationV2, updateChangeLogItem, updateDocument, updateHeaderRevision, updateOperationExample, updateStateExample, validateHeader, validateInitialState, validateModule, validateModuleOperation, validateModules, validateOperationName, validateOperations, validateStateSchemaName, verify, verifyOperationSignature, writeFileBrowser, zipEntries };
3938
5142
 
3939
5143
  //# sourceMappingURL=index.js.map