@powerhousedao/powerhouse-vetra-packages 6.2.2-dev.3 → 6.2.2-dev.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/assets/{entry-DHGZGzZJ.js → entry-Dk9VPWLt.js} +3 -2
- package/dist/browser/assets/{projection-entry-BLjins10.js → projection-entry-MT1aNJTP.js} +3 -3
- package/dist/browser/{connect-CV-z3DqA.js → connect-18dnhTvv.js} +7 -7
- package/dist/browser/{connect-CV-z3DqA.js.map → connect-18dnhTvv.js.map} +1 -1
- package/dist/browser/{dist-CXoKspdx.js → dist-B4FWbuEM.js} +10 -2
- package/dist/browser/{dist-CXoKspdx.js.map → dist-B4FWbuEM.js.map} +1 -1
- package/dist/browser/{dist-BEs8jMgM.js → dist-Bb4BpVo4.js} +1587 -1446
- package/dist/browser/dist-Bb4BpVo4.js.map +1 -0
- package/dist/browser/{dist-D8H48e8N.js → dist-D0oeNPlN.js} +1 -1
- package/dist/browser/{dist-D8H48e8N.js.map → dist-D0oeNPlN.js.map} +1 -1
- package/dist/browser/{document-drive-sTKoi6L4.js → document-drive-QCAIGn3V.js} +661 -115
- package/dist/browser/document-drive-QCAIGn3V.js.map +1 -0
- package/dist/browser/document-models/index.js +1 -1
- package/dist/browser/{documents-D4ek7Ubv.js → documents-j_qy61X1.js} +23 -622
- package/dist/browser/documents-j_qy61X1.js.map +1 -0
- package/dist/browser/{editor-Cw38euRs.js → editor-D51YfIF2.js} +10 -10
- package/dist/browser/{editor-Cw38euRs.js.map → editor-D51YfIF2.js.map} +1 -1
- package/dist/browser/{editor-DY3JsQJ3.js → editor-DjSiIu0z.js} +5 -5
- package/dist/browser/{editor-DY3JsQJ3.js.map → editor-DjSiIu0z.js.map} +1 -1
- package/dist/browser/editors/document-model-editor/module.js +1 -1
- package/dist/browser/editors/generic-drive-explorer/index.js +11 -11
- package/dist/browser/editors/generic-drive-explorer/index.js.map +1 -1
- package/dist/browser/editors/generic-drive-explorer/module.js +1 -1
- package/dist/browser/{folder-view-BQWrt8wh.js → folder-view-ChRoMADe.js} +4 -4
- package/dist/browser/{folder-view-BQWrt8wh.js.map → folder-view-ChRoMADe.js.map} +1 -1
- package/dist/browser/{graphql-editor-B-dNI5hD.js → graphql-editor-w2rhkOCs.js} +8 -7
- package/dist/browser/{graphql-editor-B-dNI5hD.js.map → graphql-editor-w2rhkOCs.js.map} +1 -1
- package/dist/browser/{hooks-CORHBNHb.js → hooks-BgIeO-WG.js} +2 -2
- package/dist/browser/{hooks-CORHBNHb.js.map → hooks-BgIeO-WG.js.map} +1 -1
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/{json-editor-v_MnzQVs.js → json-editor-DRf8YDRR.js} +4 -4
- package/dist/browser/{json-editor-v_MnzQVs.js.map → json-editor-DRf8YDRR.js.map} +1 -1
- package/dist/browser/{lib-C-f3izXz.js → lib-Dx4DRbGl.js} +2 -2
- package/dist/browser/lib-Dx4DRbGl.js.map +1 -0
- package/dist/browser/{linting-Dn6pXRkK.js → linting-nOwKxGXw.js} +6 -5
- package/dist/browser/{linting-Dn6pXRkK.js.map → linting-nOwKxGXw.js.map} +1 -1
- package/dist/browser/printer-CEYr4JOg.js +604 -0
- package/dist/browser/printer-CEYr4JOg.js.map +1 -0
- package/dist/browser/{schema-context-DY-GEGnY.js → schema-context-ClCYFYSx.js} +2 -2
- package/dist/browser/{schema-context-DY-GEGnY.js.map → schema-context-ClCYFYSx.js.map} +1 -1
- package/dist/browser/{state-schemas-65Tp0ZuG.js → state-schemas-B85E8mUI.js} +7 -7
- package/dist/browser/{state-schemas-65Tp0ZuG.js.map → state-schemas-B85E8mUI.js.map} +1 -1
- package/dist/node/{connect-Bbi5wHyR.mjs → connect-gtpzJcyJ.mjs} +6 -6
- package/dist/node/{connect-Bbi5wHyR.mjs.map → connect-gtpzJcyJ.mjs.map} +1 -1
- package/dist/node/{dist-fA4EItr0.mjs → dist-DT7jI9ol.mjs} +10 -2
- package/dist/node/{dist-fA4EItr0.mjs.map → dist-DT7jI9ol.mjs.map} +1 -1
- package/dist/node/{dist-8nCvrie2.mjs → dist-WP8o0IHv.mjs} +1592 -1446
- package/dist/node/dist-WP8o0IHv.mjs.map +1 -0
- package/dist/node/{document-drive-DjL9iikf.mjs → document-drive-DIiMiIkb.mjs} +661 -115
- package/dist/node/document-drive-DIiMiIkb.mjs.map +1 -0
- package/dist/node/document-models/index.mjs +1 -1
- package/dist/node/{documents-BFBPmyw1.mjs → documents-Bh_lxLTV.mjs} +21 -21
- package/dist/node/{documents-BFBPmyw1.mjs.map → documents-Bh_lxLTV.mjs.map} +1 -1
- package/dist/node/{editor-DkT0krRE.mjs → editor-BsQ46sh0.mjs} +9 -9
- package/dist/node/{editor-DkT0krRE.mjs.map → editor-BsQ46sh0.mjs.map} +1 -1
- package/dist/node/{editor-BH2gCDjt.mjs → editor-FWPVCfe3.mjs} +5 -5
- package/dist/node/{editor-BH2gCDjt.mjs.map → editor-FWPVCfe3.mjs.map} +1 -1
- package/dist/node/editors/document-model-editor/module.mjs +1 -1
- package/dist/node/editors/generic-drive-explorer/index.mjs +11 -11
- package/dist/node/editors/generic-drive-explorer/index.mjs.map +1 -1
- package/dist/node/editors/generic-drive-explorer/module.mjs +1 -1
- package/dist/node/{folder-view-DjKO1mAh.mjs → folder-view-BSTPPsS1.mjs} +3 -3
- package/dist/node/{folder-view-DjKO1mAh.mjs.map → folder-view-BSTPPsS1.mjs.map} +1 -1
- package/dist/node/{graphql-DskHmkMe.mjs → graphql-BfAoPeWM.mjs} +2 -2
- package/dist/node/{graphql-DskHmkMe.mjs.map → graphql-BfAoPeWM.mjs.map} +1 -1
- package/dist/node/{graphql-editor-x-d_DoqN.mjs → graphql-editor-DH27mK8m.mjs} +7 -7
- package/dist/node/{graphql-editor-x-d_DoqN.mjs.map → graphql-editor-DH27mK8m.mjs.map} +1 -1
- package/dist/node/{hooks-DJrjfVaS.mjs → hooks-B7KF2A2g.mjs} +2 -2
- package/dist/node/{hooks-DJrjfVaS.mjs.map → hooks-B7KF2A2g.mjs.map} +1 -1
- package/dist/node/index.mjs +2 -2
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/{json-editor-D8QbP3jl.mjs → json-editor-DmlYJpDQ.mjs} +4 -4
- package/dist/node/{json-editor-D8QbP3jl.mjs.map → json-editor-DmlYJpDQ.mjs.map} +1 -1
- package/dist/node/{linting-Dx50GuLN.mjs → linting-D6drcQHM.mjs} +6 -6
- package/dist/node/{linting-Dx50GuLN.mjs.map → linting-D6drcQHM.mjs.map} +1 -1
- package/dist/node/{main-D82dkD7g.mjs → main-CfVS_PlH.mjs} +4 -4
- package/dist/node/main-CfVS_PlH.mjs.map +1 -0
- package/dist/node/{schema-context-CX5ml_9t.mjs → schema-context-pefmG2VW.mjs} +3 -3
- package/dist/node/{schema-context-CX5ml_9t.mjs.map → schema-context-pefmG2VW.mjs.map} +1 -1
- package/dist/node/{state-schemas-BwvZVEhR.mjs → state-schemas-D_NQwzNn.mjs} +7 -7
- package/dist/node/{state-schemas-BwvZVEhR.mjs.map → state-schemas-D_NQwzNn.mjs.map} +1 -1
- package/package.json +6 -6
- package/dist/browser/dist-BEs8jMgM.js.map +0 -1
- package/dist/browser/document-drive-sTKoi6L4.js.map +0 -1
- package/dist/browser/documents-D4ek7Ubv.js.map +0 -1
- package/dist/browser/lib-C-f3izXz.js.map +0 -1
- package/dist/node/dist-8nCvrie2.mjs.map +0 -1
- package/dist/node/document-drive-DjL9iikf.mjs.map +0 -1
- package/dist/node/main-D82dkD7g.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as __commonJSMin, M as __toESM, S as ZodError, _ as strictObject, b as unknown, c as any, f as lazy, g as record, h as object, l as array, m as number, n as constantCase, o as _enum, p as literal, r as pascalCase, u as boolean, v as string, y as union } from "./dist-DT7jI9ol.mjs";
|
|
2
2
|
import { createRequire } from "module";
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
@@ -590,7 +590,7 @@ function isBE() {
|
|
|
590
590
|
return new Uint8Array(new Uint16Array([65279]).buffer)[0] === 254;
|
|
591
591
|
}
|
|
592
592
|
//#endregion
|
|
593
|
-
//#region ../shared/dist/utils-
|
|
593
|
+
//#region ../shared/dist/utils-CTt1XRn-.js
|
|
594
594
|
const hashBrowser = (data, algorithm = "sha1", encoding = "base64", _params) => {
|
|
595
595
|
if (!["sha1"].includes(algorithm)) throw new Error(`Hashing algorithm not supported: "${algorithm}". Available: sha1`);
|
|
596
596
|
if (!["base64", "hex"].includes(encoding)) throw new Error(`Hash encoding not supported: "${encoding}". Available: base64, hex`);
|
|
@@ -637,6 +637,40 @@ function ab2hex(ab) {
|
|
|
637
637
|
const view = ArrayBuffer.isView(ab) ? ab : new Uint8Array(ab);
|
|
638
638
|
return Array.prototype.map.call(view, (x) => ("00" + x.toString(16)).slice(-2)).join("");
|
|
639
639
|
}
|
|
640
|
+
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
641
|
+
/**
|
|
642
|
+
* Decodes a base58btc (Bitcoin/IPFS alphabet) string to bytes. Returns null on
|
|
643
|
+
* any character outside the alphabet.
|
|
644
|
+
*/
|
|
645
|
+
function base58Decode(input) {
|
|
646
|
+
const bytes = [];
|
|
647
|
+
for (const ch of input) {
|
|
648
|
+
let carry = BASE58_ALPHABET.indexOf(ch);
|
|
649
|
+
if (carry === -1) return null;
|
|
650
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
651
|
+
carry += bytes[i] * 58;
|
|
652
|
+
bytes[i] = carry & 255;
|
|
653
|
+
carry >>= 8;
|
|
654
|
+
}
|
|
655
|
+
while (carry > 0) {
|
|
656
|
+
bytes.push(carry & 255);
|
|
657
|
+
carry >>= 8;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
for (let k = 0; k < input.length && input[k] === "1"; k++) bytes.push(0);
|
|
661
|
+
return Uint8Array.from(bytes.reverse());
|
|
662
|
+
}
|
|
663
|
+
/** Decodes a base64url string to bytes (portable across node, browsers, workers). */
|
|
664
|
+
function base64UrlToBytes(input) {
|
|
665
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
666
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
667
|
+
let binary;
|
|
668
|
+
if (typeof atob === "function") binary = atob(padded);
|
|
669
|
+
else binary = Buffer.from(padded, "base64").toString("binary");
|
|
670
|
+
const bytes = new Uint8Array(binary.length);
|
|
671
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
672
|
+
return bytes;
|
|
673
|
+
}
|
|
640
674
|
function generateId(method) {
|
|
641
675
|
if (method && method.toString() !== "UUIDv4") throw new Error(`Id generation method not supported: "${method.toString()}"`);
|
|
642
676
|
return globalThis.crypto.randomUUID();
|
|
@@ -2995,6 +3029,75 @@ var DowngradeNotSupportedError = class extends Error {
|
|
|
2995
3029
|
this.toVersion = toVersion;
|
|
2996
3030
|
}
|
|
2997
3031
|
};
|
|
3032
|
+
/**
|
|
3033
|
+
* Thrown when INITIALIZE_AUTH is applied to an already-initialized auth scope.
|
|
3034
|
+
* The genesis action is valid only at auth revision zero.
|
|
3035
|
+
*/
|
|
3036
|
+
var AuthAlreadyInitializedError = class extends Error {
|
|
3037
|
+
documentId;
|
|
3038
|
+
constructor(documentId) {
|
|
3039
|
+
super(`Auth scope already initialized for document ${documentId}: INITIALIZE_AUTH is valid only at auth revision zero`);
|
|
3040
|
+
this.name = "AuthAlreadyInitializedError";
|
|
3041
|
+
this.documentId = documentId;
|
|
3042
|
+
}
|
|
3043
|
+
};
|
|
3044
|
+
/**
|
|
3045
|
+
* Thrown when INITIALIZE_AUTH is not signed by the document creator (its signer
|
|
3046
|
+
* does not match `header.sig.publicKey`), so it cannot set the auth policy.
|
|
3047
|
+
*/
|
|
3048
|
+
var AuthInitializerNotCreatorError = class extends Error {
|
|
3049
|
+
documentId;
|
|
3050
|
+
constructor(documentId) {
|
|
3051
|
+
super(`INITIALIZE_AUTH for document ${documentId} must be signed by the document creator`);
|
|
3052
|
+
this.name = "AuthInitializerNotCreatorError";
|
|
3053
|
+
this.documentId = documentId;
|
|
3054
|
+
}
|
|
3055
|
+
};
|
|
3056
|
+
/**
|
|
3057
|
+
* Thrown when INITIALIZE_AUTH carries a version below 1. Version 0 is reserved
|
|
3058
|
+
* for the uninitialized auth scope.
|
|
3059
|
+
*/
|
|
3060
|
+
var InvalidAuthVersionError = class extends Error {
|
|
3061
|
+
documentId;
|
|
3062
|
+
version;
|
|
3063
|
+
constructor(documentId, version) {
|
|
3064
|
+
super(`Invalid auth policy version ${version} for document ${documentId}: INITIALIZE_AUTH requires an integer version >= 1`);
|
|
3065
|
+
this.name = "InvalidAuthVersionError";
|
|
3066
|
+
this.documentId = documentId;
|
|
3067
|
+
this.version = version;
|
|
3068
|
+
}
|
|
3069
|
+
};
|
|
3070
|
+
/** Thrown when a duplicate would lose the source policy's version or creator binding. */
|
|
3071
|
+
var AuthPolicyNotPreservedError = class extends Error {
|
|
3072
|
+
documentId;
|
|
3073
|
+
constructor(documentId) {
|
|
3074
|
+
super(`Duplicating document ${documentId} would not preserve its auth policy: the copy loses the policy version or its creator binding`);
|
|
3075
|
+
this.name = "AuthPolicyNotPreservedError";
|
|
3076
|
+
this.documentId = documentId;
|
|
3077
|
+
}
|
|
3078
|
+
};
|
|
3079
|
+
/**
|
|
3080
|
+
* Thrown when a grant referenced by REMOVE_GRANT or MOVE_GRANT does not exist.
|
|
3081
|
+
*/
|
|
3082
|
+
var GrantNotFoundError = class extends Error {
|
|
3083
|
+
grantId;
|
|
3084
|
+
constructor(grantId) {
|
|
3085
|
+
super(`Grant not found in auth scope: ${grantId}`);
|
|
3086
|
+
this.name = "GrantNotFoundError";
|
|
3087
|
+
this.grantId = grantId;
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
/**
|
|
3091
|
+
* Thrown when a disallowed action (UNDO, REDO, PRUNE) targets the auth scope.
|
|
3092
|
+
*/
|
|
3093
|
+
var AuthActionNotAllowedError = class extends Error {
|
|
3094
|
+
actionType;
|
|
3095
|
+
constructor(actionType) {
|
|
3096
|
+
super(`${actionType} is not permitted on the auth scope`);
|
|
3097
|
+
this.name = "AuthActionNotAllowedError";
|
|
3098
|
+
this.actionType = actionType;
|
|
3099
|
+
}
|
|
3100
|
+
};
|
|
2998
3101
|
var HashMismatchError = class extends Error {
|
|
2999
3102
|
_scope;
|
|
3000
3103
|
_document;
|
|
@@ -3461,17 +3564,101 @@ const ConfigEntrySchema = object({
|
|
|
3461
3564
|
required: boolean().optional(),
|
|
3462
3565
|
default: boolean().optional()
|
|
3463
3566
|
});
|
|
3567
|
+
const PwaUrlPatternSchema = union([string(), strictObject({
|
|
3568
|
+
source: string(),
|
|
3569
|
+
flags: string().optional()
|
|
3570
|
+
}).refine((p) => {
|
|
3571
|
+
try {
|
|
3572
|
+
new RegExp(p.source, p.flags);
|
|
3573
|
+
return true;
|
|
3574
|
+
} catch {
|
|
3575
|
+
return false;
|
|
3576
|
+
}
|
|
3577
|
+
}, { message: "source/flags do not compile to a valid RegExp" })]);
|
|
3578
|
+
const PwaRuntimeCachingSchema = strictObject({
|
|
3579
|
+
urlPattern: PwaUrlPatternSchema,
|
|
3580
|
+
handler: _enum([
|
|
3581
|
+
"CacheFirst",
|
|
3582
|
+
"CacheOnly",
|
|
3583
|
+
"NetworkFirst",
|
|
3584
|
+
"NetworkOnly",
|
|
3585
|
+
"StaleWhileRevalidate"
|
|
3586
|
+
]),
|
|
3587
|
+
method: _enum([
|
|
3588
|
+
"GET",
|
|
3589
|
+
"POST",
|
|
3590
|
+
"PUT",
|
|
3591
|
+
"DELETE",
|
|
3592
|
+
"HEAD",
|
|
3593
|
+
"PATCH"
|
|
3594
|
+
]).optional(),
|
|
3595
|
+
options: strictObject({
|
|
3596
|
+
cacheName: string().optional(),
|
|
3597
|
+
networkTimeoutSeconds: number().optional(),
|
|
3598
|
+
expiration: strictObject({
|
|
3599
|
+
maxEntries: number().optional(),
|
|
3600
|
+
maxAgeSeconds: number().optional()
|
|
3601
|
+
}).optional(),
|
|
3602
|
+
cacheableResponse: strictObject({
|
|
3603
|
+
statuses: array(number()).optional(),
|
|
3604
|
+
headers: record(string(), string()).optional()
|
|
3605
|
+
}).optional()
|
|
3606
|
+
}).optional()
|
|
3607
|
+
});
|
|
3608
|
+
const PwaIconSchema = strictObject({
|
|
3609
|
+
src: string(),
|
|
3610
|
+
sizes: string().optional(),
|
|
3611
|
+
type: string().optional(),
|
|
3612
|
+
purpose: string().optional()
|
|
3613
|
+
});
|
|
3614
|
+
const PwaFileHandlerSchema = strictObject({
|
|
3615
|
+
accept: record(string(), array(string().regex(/^\./, "file extensions must start with '.'"))),
|
|
3616
|
+
icons: array(PwaIconSchema).optional(),
|
|
3617
|
+
launch_type: _enum(["single-client", "multiple-clients"]).optional()
|
|
3618
|
+
});
|
|
3619
|
+
const PwaConfigSchema = strictObject({
|
|
3620
|
+
manifest: strictObject({
|
|
3621
|
+
name: string().optional(),
|
|
3622
|
+
short_name: string().optional(),
|
|
3623
|
+
description: string().optional(),
|
|
3624
|
+
theme_color: string().optional(),
|
|
3625
|
+
background_color: string().optional(),
|
|
3626
|
+
display: _enum([
|
|
3627
|
+
"fullscreen",
|
|
3628
|
+
"standalone",
|
|
3629
|
+
"minimal-ui",
|
|
3630
|
+
"browser"
|
|
3631
|
+
]).optional(),
|
|
3632
|
+
start_url: string().optional(),
|
|
3633
|
+
scope: string().optional(),
|
|
3634
|
+
icons: array(PwaIconSchema).optional(),
|
|
3635
|
+
file_handlers: array(PwaFileHandlerSchema).optional(),
|
|
3636
|
+
launch_handler: strictObject({ client_mode: _enum([
|
|
3637
|
+
"auto",
|
|
3638
|
+
"focus-existing",
|
|
3639
|
+
"navigate-existing",
|
|
3640
|
+
"navigate-new"
|
|
3641
|
+
]) }).optional()
|
|
3642
|
+
}).optional(),
|
|
3643
|
+
globPatterns: array(string()).optional(),
|
|
3644
|
+
globIgnores: array(string()).optional(),
|
|
3645
|
+
maximumFileSizeToCacheInBytes: number().optional(),
|
|
3646
|
+
runtimeCaching: array(PwaRuntimeCachingSchema).optional(),
|
|
3647
|
+
navigateFallbackDenylist: array(PwaUrlPatternSchema).optional()
|
|
3648
|
+
});
|
|
3464
3649
|
object({
|
|
3465
3650
|
name: string(),
|
|
3466
3651
|
description: string().optional(),
|
|
3467
3652
|
category: string().optional(),
|
|
3653
|
+
image: string().optional(),
|
|
3468
3654
|
publisher: PublisherSchema.optional(),
|
|
3469
3655
|
documentModels: PowerhouseModulesSchema,
|
|
3470
3656
|
apps: PowerhouseModulesSchema,
|
|
3471
3657
|
editors: PowerhouseModulesSchema,
|
|
3472
3658
|
processors: PowerhouseModulesSchema,
|
|
3473
3659
|
subgraphs: PowerhouseModulesSchema,
|
|
3474
|
-
config: array(ConfigEntrySchema).optional()
|
|
3660
|
+
config: array(ConfigEntrySchema).optional(),
|
|
3661
|
+
pwa: PwaConfigSchema.optional()
|
|
3475
3662
|
});
|
|
3476
3663
|
/**
|
|
3477
3664
|
* Cancels the last `count` operations.
|
|
@@ -3742,6 +3929,189 @@ const actions = {
|
|
|
3742
3929
|
...baseActions,
|
|
3743
3930
|
...documentModelActions
|
|
3744
3931
|
};
|
|
3932
|
+
const documentModelDocumentType = "powerhouse/document-model";
|
|
3933
|
+
/**
|
|
3934
|
+
* Thrown when a grant violates the v1 validation rules. The message is stored
|
|
3935
|
+
* on error operations, so it must be a pure function of the input.
|
|
3936
|
+
*/
|
|
3937
|
+
var InvalidGrantError = class extends Error {
|
|
3938
|
+
grantId;
|
|
3939
|
+
constructor(grantId, problem) {
|
|
3940
|
+
super(`Invalid grant "${grantId}": ${problem}`);
|
|
3941
|
+
this.name = "InvalidGrantError";
|
|
3942
|
+
this.grantId = grantId;
|
|
3943
|
+
}
|
|
3944
|
+
};
|
|
3945
|
+
/** Thrown for a `{ group }` principal on a group document: references never chain. */
|
|
3946
|
+
var GroupPrincipalNotAllowedError = class extends Error {
|
|
3947
|
+
grantId;
|
|
3948
|
+
constructor(grantId) {
|
|
3949
|
+
super(`Grant "${grantId}" uses a group principal on a group document: a group's auth scope cannot reference other groups`);
|
|
3950
|
+
this.name = "GroupPrincipalNotAllowedError";
|
|
3951
|
+
this.grantId = grantId;
|
|
3952
|
+
}
|
|
3953
|
+
};
|
|
3954
|
+
const GRANT_KEYS = new Set([
|
|
3955
|
+
"id",
|
|
3956
|
+
"description",
|
|
3957
|
+
"effect",
|
|
3958
|
+
"principal",
|
|
3959
|
+
"capability",
|
|
3960
|
+
"where"
|
|
3961
|
+
]);
|
|
3962
|
+
const PRINCIPAL_KINDS = new Set([
|
|
3963
|
+
"anyone",
|
|
3964
|
+
"address",
|
|
3965
|
+
"group",
|
|
3966
|
+
"match"
|
|
3967
|
+
]);
|
|
3968
|
+
const COMPARISON_CONDITION_KINDS = new Set([
|
|
3969
|
+
"eq",
|
|
3970
|
+
"ne",
|
|
3971
|
+
"lt",
|
|
3972
|
+
"lte",
|
|
3973
|
+
"gt",
|
|
3974
|
+
"gte"
|
|
3975
|
+
]);
|
|
3976
|
+
function isPlainValue(value) {
|
|
3977
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3978
|
+
}
|
|
3979
|
+
function operandProblem(value, capabilityScope, budget) {
|
|
3980
|
+
budget.nodes -= 1;
|
|
3981
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
3982
|
+
if (!isPlainValue(value)) return "operand must be an object";
|
|
3983
|
+
const keys = Object.keys(value);
|
|
3984
|
+
if (keys.length !== 1) return "operand must have exactly one of attr or lit";
|
|
3985
|
+
if (keys[0] === "attr") {
|
|
3986
|
+
const attr = value.attr;
|
|
3987
|
+
if (typeof attr !== "string" || attr.length === 0) return "attr must be a non-empty string";
|
|
3988
|
+
if (capabilityScope !== void 0 && capabilityScope !== "*" && attr.startsWith("doc.")) {
|
|
3989
|
+
const pathScope = attr.split(".")[1] ?? "";
|
|
3990
|
+
if (pathScope !== capabilityScope) return `condition path "${attr}" reads scope "${pathScope}" but the capability covers only scope "${capabilityScope}"`;
|
|
3991
|
+
}
|
|
3992
|
+
return null;
|
|
3993
|
+
}
|
|
3994
|
+
if (keys[0] === "lit") {
|
|
3995
|
+
const lit = value.lit;
|
|
3996
|
+
if (lit !== null && typeof lit !== "string" && typeof lit !== "number" && typeof lit !== "boolean") return "lit must be a string, number, boolean, or null";
|
|
3997
|
+
if (typeof lit === "number" && !Number.isFinite(lit)) return "lit must be a finite number";
|
|
3998
|
+
if (typeof lit === "number" && Object.is(lit, -0)) return "lit must not be negative zero";
|
|
3999
|
+
return null;
|
|
4000
|
+
}
|
|
4001
|
+
return `unknown operand kind "${keys[0]}"`;
|
|
4002
|
+
}
|
|
4003
|
+
function conditionProblem(value, capabilityScope, depth, budget) {
|
|
4004
|
+
if (depth > 10) return `condition exceeds depth 10`;
|
|
4005
|
+
budget.nodes -= 1;
|
|
4006
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
4007
|
+
if (!isPlainValue(value)) return "condition must be an object";
|
|
4008
|
+
const keys = Object.keys(value);
|
|
4009
|
+
if (keys.length !== 1) return "condition must have exactly one operator";
|
|
4010
|
+
const kind = keys[0];
|
|
4011
|
+
const body = value[kind];
|
|
4012
|
+
if (COMPARISON_CONDITION_KINDS.has(kind)) {
|
|
4013
|
+
if (!Array.isArray(body) || body.length !== 2) return `${kind} requires a pair of operands`;
|
|
4014
|
+
for (const operand of body) {
|
|
4015
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
4016
|
+
if (problem !== null) return problem;
|
|
4017
|
+
}
|
|
4018
|
+
return null;
|
|
4019
|
+
}
|
|
4020
|
+
if (kind === "in" || kind === "notIn") {
|
|
4021
|
+
if (!Array.isArray(body) || body.length !== 2 || !Array.isArray(body[1])) return `${kind} requires an operand and an operand list`;
|
|
4022
|
+
const first = operandProblem(body[0], capabilityScope, budget);
|
|
4023
|
+
if (first !== null) return first;
|
|
4024
|
+
for (const operand of body[1]) {
|
|
4025
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
4026
|
+
if (problem !== null) return problem;
|
|
4027
|
+
}
|
|
4028
|
+
return null;
|
|
4029
|
+
}
|
|
4030
|
+
if (kind === "exists") return operandProblem(body, capabilityScope, budget);
|
|
4031
|
+
if (kind === "and" || kind === "or") {
|
|
4032
|
+
if (!Array.isArray(body)) return `${kind} requires a condition list`;
|
|
4033
|
+
for (const child of body) {
|
|
4034
|
+
const problem = conditionProblem(child, capabilityScope, depth + 1, budget);
|
|
4035
|
+
if (problem !== null) return problem;
|
|
4036
|
+
}
|
|
4037
|
+
return null;
|
|
4038
|
+
}
|
|
4039
|
+
if (kind === "not") return conditionProblem(body, capabilityScope, depth + 1, budget);
|
|
4040
|
+
return `unknown condition operator "${kind}"`;
|
|
4041
|
+
}
|
|
4042
|
+
function principalProblem(value, capabilityScope) {
|
|
4043
|
+
if (!isPlainValue(value)) return "principal must be an object";
|
|
4044
|
+
const keys = Object.keys(value);
|
|
4045
|
+
if (keys.length !== 1 || !PRINCIPAL_KINDS.has(keys[0])) return "principal must have exactly one of anyone, address, group, or match";
|
|
4046
|
+
const kind = keys[0];
|
|
4047
|
+
if (kind === "anyone" && value.anyone !== true) return "anyone must be true";
|
|
4048
|
+
if (kind === "address") {
|
|
4049
|
+
const address = value.address;
|
|
4050
|
+
if (typeof address !== "string" || address.length === 0) return "address must be a non-empty string";
|
|
4051
|
+
}
|
|
4052
|
+
if (kind === "group") {
|
|
4053
|
+
const group = value.group;
|
|
4054
|
+
if (typeof group !== "string" || group.length === 0) return "group must be a non-empty string";
|
|
4055
|
+
}
|
|
4056
|
+
if (kind === "match") return conditionProblem(value.match, capabilityScope, 1, { nodes: 100 });
|
|
4057
|
+
return null;
|
|
4058
|
+
}
|
|
4059
|
+
function capabilityProblem(value) {
|
|
4060
|
+
if (!isPlainValue(value)) return "capability must be an object";
|
|
4061
|
+
const can = value.can;
|
|
4062
|
+
if (can !== "read" && can !== "execute") return "capability.can must be read or execute";
|
|
4063
|
+
const allowedKeys = can === "execute" ? [
|
|
4064
|
+
"can",
|
|
4065
|
+
"scope",
|
|
4066
|
+
"operation"
|
|
4067
|
+
] : ["can", "scope"];
|
|
4068
|
+
const unknownKeys = Object.keys(value).filter((key) => !allowedKeys.includes(key)).sort();
|
|
4069
|
+
if (unknownKeys.length > 0) return `unknown capability key "${unknownKeys[0]}"`;
|
|
4070
|
+
if (value.scope !== void 0) {
|
|
4071
|
+
if (typeof value.scope !== "string" || value.scope.length === 0) return "capability.scope must be a non-empty string";
|
|
4072
|
+
}
|
|
4073
|
+
if (can === "execute" && value.operation !== void 0) {
|
|
4074
|
+
const operation = value.operation;
|
|
4075
|
+
if (!Array.isArray(operation)) return "capability.operation must be an array";
|
|
4076
|
+
if (operation.length > 100) return `capability.operation exceeds 100 entries`;
|
|
4077
|
+
for (const entry of operation) if (typeof entry !== "string" || entry.length === 0) return "capability.operation entries must be non-empty strings";
|
|
4078
|
+
}
|
|
4079
|
+
return null;
|
|
4080
|
+
}
|
|
4081
|
+
/** Returns the first v1-rule violation, or null. Pure, total, deterministic. */
|
|
4082
|
+
function grantProblem(value) {
|
|
4083
|
+
if (!isPlainValue(value)) return "grant must be an object";
|
|
4084
|
+
const unknownKeys = Object.keys(value).filter((key) => !GRANT_KEYS.has(key)).sort();
|
|
4085
|
+
if (unknownKeys.length > 0) return `unknown grant key "${unknownKeys[0]}"`;
|
|
4086
|
+
if (typeof value.id !== "string" || value.id.length === 0) return "id must be a non-empty string";
|
|
4087
|
+
if (typeof value.description !== "string") return "description must be a string";
|
|
4088
|
+
if (value.effect !== "allow" && value.effect !== "deny") return "effect must be allow or deny";
|
|
4089
|
+
const capabilityValue = value.capability;
|
|
4090
|
+
const capability = capabilityProblem(capabilityValue);
|
|
4091
|
+
if (capability !== null) return capability;
|
|
4092
|
+
const capabilityScope = capabilityValue.scope;
|
|
4093
|
+
const principal = principalProblem(value.principal, capabilityScope);
|
|
4094
|
+
if (principal !== null) return principal;
|
|
4095
|
+
if (value.where !== void 0) return conditionProblem(value.where, capabilityScope, 1, { nodes: 100 });
|
|
4096
|
+
return null;
|
|
4097
|
+
}
|
|
4098
|
+
/** V1 shape rules plus the group-document group-principal ban. */
|
|
4099
|
+
function assertValidGrant(grant, documentType) {
|
|
4100
|
+
const grantId = isPlainValue(grant) && typeof grant.id === "string" ? grant.id : "";
|
|
4101
|
+
const problem = grantProblem(grant);
|
|
4102
|
+
if (problem !== null) throw new InvalidGrantError(grantId, problem);
|
|
4103
|
+
if (documentType === "@powerhousedao/document-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
|
|
4104
|
+
}
|
|
4105
|
+
/** Validates an initial grant list: the count cap plus every grant. */
|
|
4106
|
+
function assertValidInitialGrants(grants, documentType) {
|
|
4107
|
+
if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
|
|
4108
|
+
for (const grant of grants) assertValidGrant(grant, documentType);
|
|
4109
|
+
}
|
|
4110
|
+
/** Validates a grant upsert: the grant itself plus the count cap on append. */
|
|
4111
|
+
function assertValidGrantUpsert(grant, existing, documentType) {
|
|
4112
|
+
assertValidGrant(grant, documentType);
|
|
4113
|
+
if (!existing.some((g) => g.id === grant.id) && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
|
|
4114
|
+
}
|
|
3745
4115
|
const documentModelFileExtension = "phdm";
|
|
3746
4116
|
const documentModelInitialLocalState = {};
|
|
3747
4117
|
const documentModelInitialGlobalState = {
|
|
@@ -4323,7 +4693,252 @@ const documentModelGlobalState = {
|
|
|
4323
4693
|
};
|
|
4324
4694
|
const HASH_ALGORITHM_SHA1 = "sha1";
|
|
4325
4695
|
const HASH_ENCODING_BASE64 = "base64";
|
|
4326
|
-
|
|
4696
|
+
/**
|
|
4697
|
+
* Creates a default PHAuthState
|
|
4698
|
+
*/
|
|
4699
|
+
function defaultAuthState() {
|
|
4700
|
+
return {
|
|
4701
|
+
version: 0,
|
|
4702
|
+
grants: []
|
|
4703
|
+
};
|
|
4704
|
+
}
|
|
4705
|
+
/**
|
|
4706
|
+
* Creates a default PHDocumentState
|
|
4707
|
+
*/
|
|
4708
|
+
function defaultDocumentState() {
|
|
4709
|
+
return {
|
|
4710
|
+
version: 0,
|
|
4711
|
+
hash: {
|
|
4712
|
+
algorithm: HASH_ALGORITHM_SHA1,
|
|
4713
|
+
encoding: HASH_ENCODING_BASE64
|
|
4714
|
+
}
|
|
4715
|
+
};
|
|
4716
|
+
}
|
|
4717
|
+
/**
|
|
4718
|
+
* Creates a default PHBaseState with auth and document properties
|
|
4719
|
+
*/
|
|
4720
|
+
function defaultBaseState() {
|
|
4721
|
+
return {
|
|
4722
|
+
auth: defaultAuthState(),
|
|
4723
|
+
document: defaultDocumentState()
|
|
4724
|
+
};
|
|
4725
|
+
}
|
|
4726
|
+
/**
|
|
4727
|
+
* Creates a PHAuthState with the given properties
|
|
4728
|
+
*/
|
|
4729
|
+
function createAuthState(auth) {
|
|
4730
|
+
return {
|
|
4731
|
+
...defaultAuthState(),
|
|
4732
|
+
...auth
|
|
4733
|
+
};
|
|
4734
|
+
}
|
|
4735
|
+
/**
|
|
4736
|
+
* Creates a PHDocumentState with the given properties
|
|
4737
|
+
*/
|
|
4738
|
+
function createDocumentState(document) {
|
|
4739
|
+
return {
|
|
4740
|
+
...defaultDocumentState(),
|
|
4741
|
+
...document
|
|
4742
|
+
};
|
|
4743
|
+
}
|
|
4744
|
+
/**
|
|
4745
|
+
* Creates a PHBaseState with the given auth and document properties
|
|
4746
|
+
*/
|
|
4747
|
+
function createBaseState(auth, document) {
|
|
4748
|
+
return {
|
|
4749
|
+
auth: createAuthState(auth),
|
|
4750
|
+
document: createDocumentState(document)
|
|
4751
|
+
};
|
|
4752
|
+
}
|
|
4753
|
+
/**
|
|
4754
|
+
* Backfills the auth scope to the default for legacy documents serialized with
|
|
4755
|
+
* an empty `auth`. Replaces only `state.auth`. Idempotent.
|
|
4756
|
+
*/
|
|
4757
|
+
function backfillAuthState(state) {
|
|
4758
|
+
return {
|
|
4759
|
+
...state,
|
|
4760
|
+
auth: createAuthState(state.auth)
|
|
4761
|
+
};
|
|
4762
|
+
}
|
|
4763
|
+
function defaultGlobalState() {
|
|
4764
|
+
return {
|
|
4765
|
+
...defaultBaseState(),
|
|
4766
|
+
author: {
|
|
4767
|
+
name: "",
|
|
4768
|
+
website: ""
|
|
4769
|
+
},
|
|
4770
|
+
description: "",
|
|
4771
|
+
extension: "",
|
|
4772
|
+
id: "",
|
|
4773
|
+
name: "",
|
|
4774
|
+
specifications: []
|
|
4775
|
+
};
|
|
4776
|
+
}
|
|
4777
|
+
function defaultLocalState() {
|
|
4778
|
+
return {};
|
|
4779
|
+
}
|
|
4780
|
+
function createGlobalState(state) {
|
|
4781
|
+
return {
|
|
4782
|
+
...defaultGlobalState(),
|
|
4783
|
+
...state || {}
|
|
4784
|
+
};
|
|
4785
|
+
}
|
|
4786
|
+
function createLocalState(state) {
|
|
4787
|
+
return {
|
|
4788
|
+
...defaultLocalState(),
|
|
4789
|
+
...state || {}
|
|
4790
|
+
};
|
|
4791
|
+
}
|
|
4792
|
+
function createState(baseState, globalState, localState) {
|
|
4793
|
+
return {
|
|
4794
|
+
...createBaseState(baseState?.auth, baseState?.document),
|
|
4795
|
+
global: createGlobalState(globalState),
|
|
4796
|
+
local: createLocalState(localState)
|
|
4797
|
+
};
|
|
4798
|
+
}
|
|
4799
|
+
/**
|
|
4800
|
+
* Destructuring a null input (reachable via raw synced operations) would
|
|
4801
|
+
* store an engine-specific TypeError message on the error operation.
|
|
4802
|
+
*/
|
|
4803
|
+
function assertActionInputShape(input) {
|
|
4804
|
+
if (!isPlainValue(input)) throw new InvalidActionInputError({ input: "must be an object" });
|
|
4805
|
+
}
|
|
4806
|
+
function withGrants(document, grants) {
|
|
4807
|
+
return {
|
|
4808
|
+
...document,
|
|
4809
|
+
state: {
|
|
4810
|
+
...document.state,
|
|
4811
|
+
auth: {
|
|
4812
|
+
...document.state.auth,
|
|
4813
|
+
grants
|
|
4814
|
+
}
|
|
4815
|
+
}
|
|
4816
|
+
};
|
|
4817
|
+
}
|
|
4818
|
+
const P256_PUBKEY_MULTICODEC = [128, 36];
|
|
4819
|
+
const DID_KEY_PREFIX = "did:key:z";
|
|
4820
|
+
function bytesEqual(a, b) {
|
|
4821
|
+
if (a.length !== b.length) return false;
|
|
4822
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
4823
|
+
return true;
|
|
4824
|
+
}
|
|
4825
|
+
/**
|
|
4826
|
+
* True when `signerKey` (an ActionSigner app key, a did:key) identifies the same
|
|
4827
|
+
* key recorded as the document creator. Returns false
|
|
4828
|
+
* when there is no creator (empty JWK) or no signer key.
|
|
4829
|
+
*/
|
|
4830
|
+
function isDocumentCreator(creatorKey, signerKey) {
|
|
4831
|
+
if (!creatorKey?.x || !creatorKey.y) return false;
|
|
4832
|
+
if (!signerKey || !signerKey.startsWith(DID_KEY_PREFIX)) return false;
|
|
4833
|
+
const decoded = base58Decode(signerKey.slice(9));
|
|
4834
|
+
if (!decoded || decoded.length !== 35) return false;
|
|
4835
|
+
if (decoded[0] !== P256_PUBKEY_MULTICODEC[0] || decoded[1] !== P256_PUBKEY_MULTICODEC[1]) return false;
|
|
4836
|
+
const parityPrefix = decoded[2];
|
|
4837
|
+
if (parityPrefix !== 2 && parityPrefix !== 3) return false;
|
|
4838
|
+
const didX = decoded.subarray(3, 35);
|
|
4839
|
+
const jwkX = base64UrlToBytes(creatorKey.x);
|
|
4840
|
+
const jwkY = base64UrlToBytes(creatorKey.y);
|
|
4841
|
+
if (jwkX.length !== 32 || jwkY.length !== 32) return false;
|
|
4842
|
+
if (!bytesEqual(didX, jwkX)) return false;
|
|
4843
|
+
return (jwkY[31] & 1) === 1 === (parityPrefix === 3);
|
|
4844
|
+
}
|
|
4845
|
+
/**
|
|
4846
|
+
* Sets the initial policy. Valid only while the auth scope is uninitialized
|
|
4847
|
+
* (version 0). The input version is the policy language version and must be an
|
|
4848
|
+
* integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
|
|
4849
|
+
* document it must be signed by the document creator (`header.sig.publicKey`).
|
|
4850
|
+
*/
|
|
4851
|
+
function applyInitializeAuthAction(document, action) {
|
|
4852
|
+
assertActionInputShape(action.input);
|
|
4853
|
+
const { version, grants } = action.input;
|
|
4854
|
+
if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
|
|
4855
|
+
if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
|
|
4856
|
+
if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
4857
|
+
assertValidInitialGrants(grants, document.header.documentType);
|
|
4858
|
+
const creatorKey = document.header.sig.publicKey;
|
|
4859
|
+
const signerKey = action.context?.signer?.app.key;
|
|
4860
|
+
const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
|
|
4861
|
+
if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
|
|
4862
|
+
const creator = hasCreator ? signerKey : void 0;
|
|
4863
|
+
return {
|
|
4864
|
+
...document,
|
|
4865
|
+
state: {
|
|
4866
|
+
...document.state,
|
|
4867
|
+
auth: createAuthState(creator ? {
|
|
4868
|
+
version,
|
|
4869
|
+
grants,
|
|
4870
|
+
creator
|
|
4871
|
+
} : {
|
|
4872
|
+
version,
|
|
4873
|
+
grants
|
|
4874
|
+
})
|
|
4875
|
+
}
|
|
4876
|
+
};
|
|
4877
|
+
}
|
|
4878
|
+
/** Upserts a grant by id: replaces in place if present, otherwise appends. */
|
|
4879
|
+
function applySetGrantAction(document, action) {
|
|
4880
|
+
assertActionInputShape(action.input);
|
|
4881
|
+
const { grant } = action.input;
|
|
4882
|
+
const grants = document.state.auth.grants;
|
|
4883
|
+
assertValidGrantUpsert(grant, grants, document.header.documentType);
|
|
4884
|
+
return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
|
|
4885
|
+
}
|
|
4886
|
+
/** Removes a grant by id; throws if the id is not present. */
|
|
4887
|
+
function applyRemoveGrantAction(document, action) {
|
|
4888
|
+
assertActionInputShape(action.input);
|
|
4889
|
+
const { id } = action.input;
|
|
4890
|
+
const grants = document.state.auth.grants;
|
|
4891
|
+
if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
|
|
4892
|
+
return withGrants(document, grants.filter((g) => g.id !== id));
|
|
4893
|
+
}
|
|
4894
|
+
/**
|
|
4895
|
+
* Moves a grant by id to a new index. Order is load-bearing (the last
|
|
4896
|
+
* applicable grant wins), so the relative order of the other grants is kept.
|
|
4897
|
+
* The target index is clamped to the valid range; an unknown id throws.
|
|
4898
|
+
*/
|
|
4899
|
+
function applyMoveGrantAction(document, action) {
|
|
4900
|
+
assertActionInputShape(action.input);
|
|
4901
|
+
const { id, index } = action.input;
|
|
4902
|
+
const grants = document.state.auth.grants;
|
|
4903
|
+
const from = grants.findIndex((g) => g.id === id);
|
|
4904
|
+
if (from === -1) throw new GrantNotFoundError(id);
|
|
4905
|
+
const next = [...grants];
|
|
4906
|
+
const [moved] = next.splice(from, 1);
|
|
4907
|
+
const to = Math.max(0, Math.min(index, next.length));
|
|
4908
|
+
next.splice(to, 0, moved);
|
|
4909
|
+
return withGrants(document, next);
|
|
4910
|
+
}
|
|
4911
|
+
/**
|
|
4912
|
+
* Dispatches an auth-scope action to its handler. This is the auth scope's
|
|
4913
|
+
* dedicated reducer: it is applied by the base reducer instead of the model
|
|
4914
|
+
* reducer, mirroring the document-scope platform handlers. Unknown types are a
|
|
4915
|
+
* no-op, matching the model-reducer default.
|
|
4916
|
+
*/
|
|
4917
|
+
function applyAuthAction(document, action) {
|
|
4918
|
+
switch (action.type) {
|
|
4919
|
+
case "INITIALIZE_AUTH": return applyInitializeAuthAction(document, action);
|
|
4920
|
+
case "SET_GRANT": return applySetGrantAction(document, action);
|
|
4921
|
+
case "REMOVE_GRANT": return applyRemoveGrantAction(document, action);
|
|
4922
|
+
case "MOVE_GRANT": return applyMoveGrantAction(document, action);
|
|
4923
|
+
default: return document;
|
|
4924
|
+
}
|
|
4925
|
+
}
|
|
4926
|
+
/**
|
|
4927
|
+
* Because only creators can initialize auth scopes, we must verify that either
|
|
4928
|
+
* the document has no auth or the version and creator match.
|
|
4929
|
+
*/
|
|
4930
|
+
function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
|
|
4931
|
+
if (!source || source.version === 0) return;
|
|
4932
|
+
if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
|
|
4933
|
+
}
|
|
4934
|
+
/** UNDO, REDO and PRUNE are rejected on the auth scope. */
|
|
4935
|
+
function assertAuthScopeActionAllowed(action) {
|
|
4936
|
+
if (action.scope === "auth" && [
|
|
4937
|
+
"UNDO",
|
|
4938
|
+
"REDO",
|
|
4939
|
+
"PRUNE"
|
|
4940
|
+
].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
|
|
4941
|
+
}
|
|
4327
4942
|
const BaseDocumentHeaderSchema = object({
|
|
4328
4943
|
id: string(),
|
|
4329
4944
|
name: string(),
|
|
@@ -4454,6 +5069,7 @@ function createDocumentScopeOperations(header, state) {
|
|
|
4454
5069
|
function baseCreateDocument(createState, initialState, documentType = "") {
|
|
4455
5070
|
const state = createState(initialState);
|
|
4456
5071
|
const header = createPresignedHeader(generateId(), documentType);
|
|
5072
|
+
header.protocolVersions = { "base-reducer": 2 };
|
|
4457
5073
|
return {
|
|
4458
5074
|
header,
|
|
4459
5075
|
state,
|
|
@@ -4477,6 +5093,18 @@ function hashDocumentStateForScope(document, scope = "global") {
|
|
|
4477
5093
|
* Uses the V2 model where consecutive NOOPs form chains.
|
|
4478
5094
|
* Unlike V1 garbageCollect, this preserves ALL operations but marks which to apply.
|
|
4479
5095
|
*/
|
|
5096
|
+
/**
|
|
5097
|
+
* The base-reducer protocol version a document is written against. Every
|
|
5098
|
+
* document carries one, set from the CREATE_DOCUMENT input. A header without
|
|
5099
|
+
* one was built outside that path, and choosing a version on its behalf would
|
|
5100
|
+
* replay the document through a reducer it was not written for, so it is an
|
|
5101
|
+
* error rather than a default.
|
|
5102
|
+
*/
|
|
5103
|
+
function baseReducerVersion(header) {
|
|
5104
|
+
const version = header.protocolVersions?.["base-reducer"];
|
|
5105
|
+
if (typeof version !== "number") throw new Error(`Document ${header.id} carries no base-reducer protocol version`);
|
|
5106
|
+
return version;
|
|
5107
|
+
}
|
|
4480
5108
|
function garbageCollectV2(sortedOperations) {
|
|
4481
5109
|
const result = [];
|
|
4482
5110
|
let noopChainLength = 0;
|
|
@@ -4495,7 +5123,8 @@ const defaultCreateState = (state) => {
|
|
|
4495
5123
|
};
|
|
4496
5124
|
function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
|
|
4497
5125
|
const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
|
|
4498
|
-
|
|
5126
|
+
const backfilledInitialState = backfillAuthState(initialState);
|
|
5127
|
+
let documentState = backfilledInitialState;
|
|
4499
5128
|
const operationsToReplay = [];
|
|
4500
5129
|
const allScopes = new Set([
|
|
4501
5130
|
...Object.keys(operations),
|
|
@@ -4530,7 +5159,7 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
|
|
|
4530
5159
|
const document = {
|
|
4531
5160
|
header,
|
|
4532
5161
|
state: defaultCreateState(documentState),
|
|
4533
|
-
initialState,
|
|
5162
|
+
initialState: backfilledInitialState,
|
|
4534
5163
|
operations: initialOperations,
|
|
4535
5164
|
clipboard: []
|
|
4536
5165
|
};
|
|
@@ -4823,7 +5452,7 @@ function loadStateOperation(document, action) {
|
|
|
4823
5452
|
...document.header,
|
|
4824
5453
|
name: action.state.name
|
|
4825
5454
|
},
|
|
4826
|
-
state: action.state.data
|
|
5455
|
+
state: backfillAuthState(action.state.data)
|
|
4827
5456
|
};
|
|
4828
5457
|
}
|
|
4829
5458
|
function replayOperations(initialState, clearedOperations, stateReducer, header, dispatch, documentReducer = baseReducer, skipHeaderOperations = {}, options) {
|
|
@@ -4997,6 +5626,7 @@ function processUndoOperation(document, scope, customReducer, reuseOperationResu
|
|
|
4997
5626
|
function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
4998
5627
|
const { skip, ignoreSkipOperations = false, reuseOperationResultingState = false, operationResultingStateParser, pruneOnSkip = true, branch = "main" } = options;
|
|
4999
5628
|
let _action = actionFromAction(action);
|
|
5629
|
+
assertAuthScopeActionAllowed(_action);
|
|
5000
5630
|
let skipValue = skip ?? options.replayOptions?.operation.skip ?? 0;
|
|
5001
5631
|
let newDocument = { ...document };
|
|
5002
5632
|
let reuseLastOperationIndex = false;
|
|
@@ -5044,6 +5674,13 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
|
5044
5674
|
}
|
|
5045
5675
|
newDocument = create(newDocument, (draft) => {
|
|
5046
5676
|
try {
|
|
5677
|
+
if (_action.scope === "auth") {
|
|
5678
|
+
const authState = applyAuthAction(newDocument, _action).state;
|
|
5679
|
+
unsafe(() => {
|
|
5680
|
+
draft.state = castDraft(authState);
|
|
5681
|
+
});
|
|
5682
|
+
return;
|
|
5683
|
+
}
|
|
5047
5684
|
const newState = customReducer(draft.state, _action, dispatch);
|
|
5048
5685
|
if (newState) unsafe(() => {
|
|
5049
5686
|
draft.state = castDraft(newState);
|
|
@@ -5837,10 +6474,10 @@ function applyInitialState(document, action) {
|
|
|
5837
6474
|
const input = action.input;
|
|
5838
6475
|
const newState = input.initialState || input.state;
|
|
5839
6476
|
if (newState) {
|
|
5840
|
-
document.state = {
|
|
6477
|
+
document.state = backfillAuthState({
|
|
5841
6478
|
...document.state,
|
|
5842
6479
|
...newState
|
|
5843
|
-
};
|
|
6480
|
+
});
|
|
5844
6481
|
document.initialState = document.state;
|
|
5845
6482
|
}
|
|
5846
6483
|
}
|
|
@@ -5900,7 +6537,6 @@ function computeUpgradeTransitions(manifest, fromVersion, toVersion) {
|
|
|
5900
6537
|
}
|
|
5901
6538
|
return transitions;
|
|
5902
6539
|
}
|
|
5903
|
-
const NON_DOMAIN_SCOPES$1 = new Set(["auth", "document"]);
|
|
5904
6540
|
function highestReducerVersion(reducers) {
|
|
5905
6541
|
const keys = Object.keys(reducers).map(Number);
|
|
5906
6542
|
if (keys.length === 0) throw new Error("VersionedReplayConfig.reducers must not be empty");
|
|
@@ -5928,15 +6564,15 @@ function highestReducerVersion(reducers) {
|
|
|
5928
6564
|
*/
|
|
5929
6565
|
function replayDocumentVersioned(initialState, operations, config, header, dispatch, options) {
|
|
5930
6566
|
const { checkHashes = true, skipIndexValidation } = options || {};
|
|
5931
|
-
const protocolVersion = header
|
|
6567
|
+
const protocolVersion = baseReducerVersion(header);
|
|
5932
6568
|
const spine = (operations["document"] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
5933
6569
|
const upgrades = spine.filter((op) => op.action.type === "UPGRADE_DOCUMENT");
|
|
5934
6570
|
const legacyFallback = () => {
|
|
5935
|
-
const
|
|
6571
|
+
const replayOps = Object.fromEntries(Object.entries(operations).filter(([s]) => s !== "document"));
|
|
5936
6572
|
const latestVersion = highestReducerVersion(config.reducers);
|
|
5937
6573
|
const reducer = config.reducers[latestVersion];
|
|
5938
6574
|
return {
|
|
5939
|
-
...replayDocument(initialState,
|
|
6575
|
+
...replayDocument(initialState, replayOps, reducer, header, dispatch, {}, options),
|
|
5940
6576
|
operations
|
|
5941
6577
|
};
|
|
5942
6578
|
};
|
|
@@ -5960,14 +6596,14 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5960
6596
|
const a = op.action;
|
|
5961
6597
|
return a.input.fromVersion > 0 && a.input.fromVersion < a.input.toVersion;
|
|
5962
6598
|
});
|
|
5963
|
-
const
|
|
6599
|
+
const replayScopes = Object.keys(operations).filter((s) => s !== "document");
|
|
5964
6600
|
const scopeOps = {};
|
|
5965
|
-
for (const s of
|
|
6601
|
+
for (const s of replayScopes) scopeOps[s] = (operations[s] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
5966
6602
|
const boundaries = validatedUpgrades.map((upgradeOp) => {
|
|
5967
6603
|
const revisionSnapshot = upgradeOp.action.input.revision;
|
|
5968
6604
|
const upgradeTimestamp = upgradeOp.timestampUtcMs;
|
|
5969
6605
|
const boundary = {};
|
|
5970
|
-
for (const s of
|
|
6606
|
+
for (const s of replayScopes) {
|
|
5971
6607
|
const ops = scopeOps[s] ?? [];
|
|
5972
6608
|
if (revisionSnapshot !== void 0) {
|
|
5973
6609
|
const rev = revisionSnapshot[s] ?? 0;
|
|
@@ -5985,7 +6621,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5985
6621
|
}
|
|
5986
6622
|
return boundary;
|
|
5987
6623
|
});
|
|
5988
|
-
for (let i = 1; i < boundaries.length; i++) for (const s of
|
|
6624
|
+
for (let i = 1; i < boundaries.length; i++) for (const s of replayScopes) {
|
|
5989
6625
|
const prev = boundaries[i - 1]?.[s] ?? 0;
|
|
5990
6626
|
const curr = boundaries[i]?.[s] ?? 0;
|
|
5991
6627
|
if (boundaries[i]) boundaries[i][s] = Math.max(prev, curr);
|
|
@@ -5997,10 +6633,11 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5997
6633
|
]);
|
|
5998
6634
|
const initialOperations = {};
|
|
5999
6635
|
for (const s of allScopes) initialOperations[s] = [];
|
|
6636
|
+
const backfilledSeed = backfillAuthState(seedState);
|
|
6000
6637
|
let document = {
|
|
6001
6638
|
header,
|
|
6002
|
-
state:
|
|
6003
|
-
initialState:
|
|
6639
|
+
state: backfilledSeed,
|
|
6640
|
+
initialState: backfilledSeed,
|
|
6004
6641
|
operations: initialOperations,
|
|
6005
6642
|
clipboard: []
|
|
6006
6643
|
};
|
|
@@ -6012,7 +6649,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6012
6649
|
const available = Object.keys(config.reducers).join(", ");
|
|
6013
6650
|
throw new Error(`No reducer registered for document version ${currentVersion}. Available versions: ${available}`);
|
|
6014
6651
|
}
|
|
6015
|
-
for (const s of
|
|
6652
|
+
for (const s of replayScopes) {
|
|
6016
6653
|
const ops = scopeOps[s] ?? [];
|
|
6017
6654
|
const segStart = k === 0 ? 0 : boundaries[k - 1]?.[s] ?? 0;
|
|
6018
6655
|
const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
|
|
@@ -6065,7 +6702,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6065
6702
|
}
|
|
6066
6703
|
};
|
|
6067
6704
|
if (!checkHashes) {
|
|
6068
|
-
const allReplayedOps =
|
|
6705
|
+
const allReplayedOps = replayScopes.flatMap((s) => scopeOps[s] ?? []);
|
|
6069
6706
|
for (const scope of Object.keys(document.state)) {
|
|
6070
6707
|
const capturedHash = segmentEndHashPerScope.get(scope);
|
|
6071
6708
|
const scopeHash = capturedHash !== void 0 ? capturedHash : hashDocumentStateForScope(document, scope);
|
|
@@ -6107,7 +6744,6 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6107
6744
|
}
|
|
6108
6745
|
};
|
|
6109
6746
|
}
|
|
6110
|
-
const NON_DOMAIN_SCOPES = new Set(["auth", "document"]);
|
|
6111
6747
|
function zipAsync(data) {
|
|
6112
6748
|
return new Promise((resolve, reject) => {
|
|
6113
6749
|
zip(data, (err, out) => err ? reject(err) : resolve(out));
|
|
@@ -6186,7 +6822,7 @@ async function parseZipData(data) {
|
|
|
6186
6822
|
async function loadFromZipData(data, reducer, options) {
|
|
6187
6823
|
const { initialState, header, clearedOperations } = await parseZipData(data);
|
|
6188
6824
|
return {
|
|
6189
|
-
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) =>
|
|
6825
|
+
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) => scope !== "document")), reducer, header, void 0, {}, options),
|
|
6190
6826
|
operations: clearedOperations
|
|
6191
6827
|
};
|
|
6192
6828
|
}
|
|
@@ -6209,96 +6845,6 @@ const documentModelLoadFromInput = (input) => {
|
|
|
6209
6845
|
const documentModelSaveToFileHandle = (document, input) => {
|
|
6210
6846
|
return baseSaveToFileHandle(document, input);
|
|
6211
6847
|
};
|
|
6212
|
-
/**
|
|
6213
|
-
* Creates a default PHAuthState
|
|
6214
|
-
*/
|
|
6215
|
-
function defaultAuthState() {
|
|
6216
|
-
return {};
|
|
6217
|
-
}
|
|
6218
|
-
/**
|
|
6219
|
-
* Creates a default PHDocumentState
|
|
6220
|
-
*/
|
|
6221
|
-
function defaultDocumentState() {
|
|
6222
|
-
return {
|
|
6223
|
-
version: 0,
|
|
6224
|
-
hash: {
|
|
6225
|
-
algorithm: HASH_ALGORITHM_SHA1,
|
|
6226
|
-
encoding: HASH_ENCODING_BASE64
|
|
6227
|
-
}
|
|
6228
|
-
};
|
|
6229
|
-
}
|
|
6230
|
-
/**
|
|
6231
|
-
* Creates a default PHBaseState with auth and document properties
|
|
6232
|
-
*/
|
|
6233
|
-
function defaultBaseState() {
|
|
6234
|
-
return {
|
|
6235
|
-
auth: defaultAuthState(),
|
|
6236
|
-
document: defaultDocumentState()
|
|
6237
|
-
};
|
|
6238
|
-
}
|
|
6239
|
-
/**
|
|
6240
|
-
* Creates a PHAuthState with the given properties
|
|
6241
|
-
*/
|
|
6242
|
-
function createAuthState(auth) {
|
|
6243
|
-
return {
|
|
6244
|
-
...defaultAuthState(),
|
|
6245
|
-
...auth
|
|
6246
|
-
};
|
|
6247
|
-
}
|
|
6248
|
-
/**
|
|
6249
|
-
* Creates a PHDocumentState with the given properties
|
|
6250
|
-
*/
|
|
6251
|
-
function createDocumentState(document) {
|
|
6252
|
-
return {
|
|
6253
|
-
...defaultDocumentState(),
|
|
6254
|
-
...document
|
|
6255
|
-
};
|
|
6256
|
-
}
|
|
6257
|
-
/**
|
|
6258
|
-
* Creates a PHBaseState with the given auth and document properties
|
|
6259
|
-
*/
|
|
6260
|
-
function createBaseState(auth, document) {
|
|
6261
|
-
return {
|
|
6262
|
-
auth: createAuthState(auth),
|
|
6263
|
-
document: createDocumentState(document)
|
|
6264
|
-
};
|
|
6265
|
-
}
|
|
6266
|
-
function defaultGlobalState() {
|
|
6267
|
-
return {
|
|
6268
|
-
...defaultBaseState(),
|
|
6269
|
-
author: {
|
|
6270
|
-
name: "",
|
|
6271
|
-
website: ""
|
|
6272
|
-
},
|
|
6273
|
-
description: "",
|
|
6274
|
-
extension: "",
|
|
6275
|
-
id: "",
|
|
6276
|
-
name: "",
|
|
6277
|
-
specifications: []
|
|
6278
|
-
};
|
|
6279
|
-
}
|
|
6280
|
-
function defaultLocalState() {
|
|
6281
|
-
return {};
|
|
6282
|
-
}
|
|
6283
|
-
function createGlobalState(state) {
|
|
6284
|
-
return {
|
|
6285
|
-
...defaultGlobalState(),
|
|
6286
|
-
...state || {}
|
|
6287
|
-
};
|
|
6288
|
-
}
|
|
6289
|
-
function createLocalState(state) {
|
|
6290
|
-
return {
|
|
6291
|
-
...defaultLocalState(),
|
|
6292
|
-
...state || {}
|
|
6293
|
-
};
|
|
6294
|
-
}
|
|
6295
|
-
function createState(baseState, globalState, localState) {
|
|
6296
|
-
return {
|
|
6297
|
-
...createBaseState(baseState?.auth, baseState?.document),
|
|
6298
|
-
global: createGlobalState(globalState),
|
|
6299
|
-
local: createLocalState(localState)
|
|
6300
|
-
};
|
|
6301
|
-
}
|
|
6302
6848
|
//#endregion
|
|
6303
6849
|
//#region ../document-model/dist/index.js
|
|
6304
6850
|
const isStateOfType$1 = (state) => {
|
|
@@ -7377,6 +7923,6 @@ const driveDocumentModelModule = {
|
|
|
7377
7923
|
}
|
|
7378
7924
|
};
|
|
7379
7925
|
//#endregion
|
|
7380
|
-
export {
|
|
7926
|
+
export { hashDocumentStateForScope as A, setModelName as B, createState as C, deleteOperation as D, deleteModule as E, setAuthorWebsite as F, setOperationName as G, setName as H, setInitialState as I, undo as J, setOperationSchema as K, setModelDescription as L, redo as M, replayDocumentVersioned as N, deleteOperationError as O, setAuthorName as P, generateId as Q, setModelExtension as R, createReducer as S, defaultBaseState as T, setOperationDescription as U, setModuleName as V, setOperationErrorName as W, validateModules as X, validateInitialState as Y, validateStateSchemaName as Z, baseLoadFromInput as _, handleTargetNameCollisions as a, buildSignedAction as b, moveNode as c, logger as d, addModule as f, baseCreateDocument as g, assertAuthPreservedOnDuplicate as h, generateNodesCopy as i, isDocumentAction as j, documentModelDocumentType as k, updateNode as l, addOperationError as m, copyNode as n, isFileNode as o, addOperation as p, setStateSchema as q, driveDocumentModelModule as r, isFolderNode as s, addFolder as t, documentModelDocumentModelModule as u, baseLoadFromInputVersioned as v, createZip as w, createPresignedHeader as x, baseSaveToFileHandle as y, setModelId as z };
|
|
7381
7927
|
|
|
7382
|
-
//# sourceMappingURL=document-drive-
|
|
7928
|
+
//# sourceMappingURL=document-drive-DIiMiIkb.mjs.map
|