@powerhousedao/powerhouse-vetra-packages 6.2.2-dev.3 → 6.2.2-dev.30
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-DxWdRwsm.js} +7 -7
- package/dist/browser/{connect-CV-z3DqA.js.map → connect-DxWdRwsm.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-D8H48e8N.js → dist-D0oeNPlN.js} +1 -1
- package/dist/browser/{dist-D8H48e8N.js.map → dist-D0oeNPlN.js.map} +1 -1
- package/dist/browser/{dist-BEs8jMgM.js → dist-MZEJuHR7.js} +1587 -1446
- package/dist/browser/dist-MZEJuHR7.js.map +1 -0
- 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-DY3JsQJ3.js → editor-Bx3LD-h5.js} +5 -5
- package/dist/browser/{editor-DY3JsQJ3.js.map → editor-Bx3LD-h5.js.map} +1 -1
- package/dist/browser/{editor-Cw38euRs.js → editor-uF7BbCVq.js} +10 -10
- package/dist/browser/{editor-Cw38euRs.js.map → editor-uF7BbCVq.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-DJY82x3P.js} +4 -4
- package/dist/browser/{folder-view-BQWrt8wh.js.map → folder-view-DJY82x3P.js.map} +1 -1
- package/dist/browser/{graphql-editor-B-dNI5hD.js → graphql-editor-Tj-ymH1Y.js} +8 -7
- package/dist/browser/{graphql-editor-B-dNI5hD.js.map → graphql-editor-Tj-ymH1Y.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-DtraN4qF.js} +4 -4
- package/dist/browser/{json-editor-v_MnzQVs.js.map → json-editor-DtraN4qF.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-ByvJfV_L.js} +7 -7
- package/dist/browser/{state-schemas-65Tp0ZuG.js.map → state-schemas-ByvJfV_L.js.map} +1 -1
- package/dist/node/{connect-Bbi5wHyR.mjs → connect-B10Y6fME.mjs} +6 -6
- package/dist/node/{connect-Bbi5wHyR.mjs.map → connect-B10Y6fME.mjs.map} +1 -1
- package/dist/node/{dist-8nCvrie2.mjs → dist-DKCrbRL1.mjs} +1592 -1446
- package/dist/node/dist-DKCrbRL1.mjs.map +1 -0
- 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/{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-BH2gCDjt.mjs → editor-BANkGXoZ.mjs} +5 -5
- package/dist/node/{editor-BH2gCDjt.mjs.map → editor-BANkGXoZ.mjs.map} +1 -1
- package/dist/node/{editor-DkT0krRE.mjs → editor-BVa1qLDP.mjs} +9 -9
- package/dist/node/{editor-DkT0krRE.mjs.map → editor-BVa1qLDP.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-CgVpQdRu.mjs} +3 -3
- package/dist/node/{folder-view-DjKO1mAh.mjs.map → folder-view-CgVpQdRu.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-Cc1_-bA1.mjs} +7 -7
- package/dist/node/{graphql-editor-x-d_DoqN.mjs.map → graphql-editor-Cc1_-bA1.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-D1F087U2.mjs} +4 -4
- package/dist/node/{json-editor-D8QbP3jl.mjs.map → json-editor-D1F087U2.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-XxBrdwR9.mjs} +7 -7
- package/dist/node/{state-schemas-BwvZVEhR.mjs.map → state-schemas-XxBrdwR9.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 { A as __toESM, D as __commonJSMin, 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-B4FWbuEM.js";
|
|
2
2
|
//#endregion
|
|
3
3
|
//#region ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
4
4
|
var import_safe_stable_stringify = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
@@ -589,7 +589,7 @@ function isBE() {
|
|
|
589
589
|
return new Uint8Array(new Uint16Array([65279]).buffer)[0] === 254;
|
|
590
590
|
}
|
|
591
591
|
//#endregion
|
|
592
|
-
//#region ../shared/dist/utils-
|
|
592
|
+
//#region ../shared/dist/utils-CTt1XRn-.js
|
|
593
593
|
const hashBrowser = (data, algorithm = "sha1", encoding = "base64", _params) => {
|
|
594
594
|
if (!["sha1"].includes(algorithm)) throw new Error(`Hashing algorithm not supported: "${algorithm}". Available: sha1`);
|
|
595
595
|
if (!["base64", "hex"].includes(encoding)) throw new Error(`Hash encoding not supported: "${encoding}". Available: base64, hex`);
|
|
@@ -636,6 +636,40 @@ function ab2hex(ab) {
|
|
|
636
636
|
const view = ArrayBuffer.isView(ab) ? ab : new Uint8Array(ab);
|
|
637
637
|
return Array.prototype.map.call(view, (x) => ("00" + x.toString(16)).slice(-2)).join("");
|
|
638
638
|
}
|
|
639
|
+
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
640
|
+
/**
|
|
641
|
+
* Decodes a base58btc (Bitcoin/IPFS alphabet) string to bytes. Returns null on
|
|
642
|
+
* any character outside the alphabet.
|
|
643
|
+
*/
|
|
644
|
+
function base58Decode(input) {
|
|
645
|
+
const bytes = [];
|
|
646
|
+
for (const ch of input) {
|
|
647
|
+
let carry = BASE58_ALPHABET.indexOf(ch);
|
|
648
|
+
if (carry === -1) return null;
|
|
649
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
650
|
+
carry += bytes[i] * 58;
|
|
651
|
+
bytes[i] = carry & 255;
|
|
652
|
+
carry >>= 8;
|
|
653
|
+
}
|
|
654
|
+
while (carry > 0) {
|
|
655
|
+
bytes.push(carry & 255);
|
|
656
|
+
carry >>= 8;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
for (let k = 0; k < input.length && input[k] === "1"; k++) bytes.push(0);
|
|
660
|
+
return Uint8Array.from(bytes.reverse());
|
|
661
|
+
}
|
|
662
|
+
/** Decodes a base64url string to bytes (portable across node, browsers, workers). */
|
|
663
|
+
function base64UrlToBytes(input) {
|
|
664
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
665
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
666
|
+
let binary;
|
|
667
|
+
if (typeof atob === "function") binary = atob(padded);
|
|
668
|
+
else binary = Buffer.from(padded, "base64").toString("binary");
|
|
669
|
+
const bytes = new Uint8Array(binary.length);
|
|
670
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
671
|
+
return bytes;
|
|
672
|
+
}
|
|
639
673
|
function generateId(method) {
|
|
640
674
|
if (method && method.toString() !== "UUIDv4") throw new Error(`Id generation method not supported: "${method.toString()}"`);
|
|
641
675
|
return globalThis.crypto.randomUUID();
|
|
@@ -2978,6 +3012,75 @@ var DowngradeNotSupportedError = class extends Error {
|
|
|
2978
3012
|
this.toVersion = toVersion;
|
|
2979
3013
|
}
|
|
2980
3014
|
};
|
|
3015
|
+
/**
|
|
3016
|
+
* Thrown when INITIALIZE_AUTH is applied to an already-initialized auth scope.
|
|
3017
|
+
* The genesis action is valid only at auth revision zero.
|
|
3018
|
+
*/
|
|
3019
|
+
var AuthAlreadyInitializedError = class extends Error {
|
|
3020
|
+
documentId;
|
|
3021
|
+
constructor(documentId) {
|
|
3022
|
+
super(`Auth scope already initialized for document ${documentId}: INITIALIZE_AUTH is valid only at auth revision zero`);
|
|
3023
|
+
this.name = "AuthAlreadyInitializedError";
|
|
3024
|
+
this.documentId = documentId;
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
3027
|
+
/**
|
|
3028
|
+
* Thrown when INITIALIZE_AUTH is not signed by the document creator (its signer
|
|
3029
|
+
* does not match `header.sig.publicKey`), so it cannot set the auth policy.
|
|
3030
|
+
*/
|
|
3031
|
+
var AuthInitializerNotCreatorError = class extends Error {
|
|
3032
|
+
documentId;
|
|
3033
|
+
constructor(documentId) {
|
|
3034
|
+
super(`INITIALIZE_AUTH for document ${documentId} must be signed by the document creator`);
|
|
3035
|
+
this.name = "AuthInitializerNotCreatorError";
|
|
3036
|
+
this.documentId = documentId;
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
3039
|
+
/**
|
|
3040
|
+
* Thrown when INITIALIZE_AUTH carries a version below 1. Version 0 is reserved
|
|
3041
|
+
* for the uninitialized auth scope.
|
|
3042
|
+
*/
|
|
3043
|
+
var InvalidAuthVersionError = class extends Error {
|
|
3044
|
+
documentId;
|
|
3045
|
+
version;
|
|
3046
|
+
constructor(documentId, version) {
|
|
3047
|
+
super(`Invalid auth policy version ${version} for document ${documentId}: INITIALIZE_AUTH requires an integer version >= 1`);
|
|
3048
|
+
this.name = "InvalidAuthVersionError";
|
|
3049
|
+
this.documentId = documentId;
|
|
3050
|
+
this.version = version;
|
|
3051
|
+
}
|
|
3052
|
+
};
|
|
3053
|
+
/** Thrown when a duplicate would lose the source policy's version or creator binding. */
|
|
3054
|
+
var AuthPolicyNotPreservedError = class extends Error {
|
|
3055
|
+
documentId;
|
|
3056
|
+
constructor(documentId) {
|
|
3057
|
+
super(`Duplicating document ${documentId} would not preserve its auth policy: the copy loses the policy version or its creator binding`);
|
|
3058
|
+
this.name = "AuthPolicyNotPreservedError";
|
|
3059
|
+
this.documentId = documentId;
|
|
3060
|
+
}
|
|
3061
|
+
};
|
|
3062
|
+
/**
|
|
3063
|
+
* Thrown when a grant referenced by REMOVE_GRANT or MOVE_GRANT does not exist.
|
|
3064
|
+
*/
|
|
3065
|
+
var GrantNotFoundError = class extends Error {
|
|
3066
|
+
grantId;
|
|
3067
|
+
constructor(grantId) {
|
|
3068
|
+
super(`Grant not found in auth scope: ${grantId}`);
|
|
3069
|
+
this.name = "GrantNotFoundError";
|
|
3070
|
+
this.grantId = grantId;
|
|
3071
|
+
}
|
|
3072
|
+
};
|
|
3073
|
+
/**
|
|
3074
|
+
* Thrown when a disallowed action (UNDO, REDO, PRUNE) targets the auth scope.
|
|
3075
|
+
*/
|
|
3076
|
+
var AuthActionNotAllowedError = class extends Error {
|
|
3077
|
+
actionType;
|
|
3078
|
+
constructor(actionType) {
|
|
3079
|
+
super(`${actionType} is not permitted on the auth scope`);
|
|
3080
|
+
this.name = "AuthActionNotAllowedError";
|
|
3081
|
+
this.actionType = actionType;
|
|
3082
|
+
}
|
|
3083
|
+
};
|
|
2981
3084
|
var HashMismatchError = class extends Error {
|
|
2982
3085
|
_scope;
|
|
2983
3086
|
_document;
|
|
@@ -3444,17 +3547,101 @@ const ConfigEntrySchema = object({
|
|
|
3444
3547
|
required: boolean().optional(),
|
|
3445
3548
|
default: boolean().optional()
|
|
3446
3549
|
});
|
|
3550
|
+
const PwaUrlPatternSchema = union([string(), strictObject({
|
|
3551
|
+
source: string(),
|
|
3552
|
+
flags: string().optional()
|
|
3553
|
+
}).refine((p) => {
|
|
3554
|
+
try {
|
|
3555
|
+
new RegExp(p.source, p.flags);
|
|
3556
|
+
return true;
|
|
3557
|
+
} catch {
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3560
|
+
}, { message: "source/flags do not compile to a valid RegExp" })]);
|
|
3561
|
+
const PwaRuntimeCachingSchema = strictObject({
|
|
3562
|
+
urlPattern: PwaUrlPatternSchema,
|
|
3563
|
+
handler: _enum([
|
|
3564
|
+
"CacheFirst",
|
|
3565
|
+
"CacheOnly",
|
|
3566
|
+
"NetworkFirst",
|
|
3567
|
+
"NetworkOnly",
|
|
3568
|
+
"StaleWhileRevalidate"
|
|
3569
|
+
]),
|
|
3570
|
+
method: _enum([
|
|
3571
|
+
"GET",
|
|
3572
|
+
"POST",
|
|
3573
|
+
"PUT",
|
|
3574
|
+
"DELETE",
|
|
3575
|
+
"HEAD",
|
|
3576
|
+
"PATCH"
|
|
3577
|
+
]).optional(),
|
|
3578
|
+
options: strictObject({
|
|
3579
|
+
cacheName: string().optional(),
|
|
3580
|
+
networkTimeoutSeconds: number().optional(),
|
|
3581
|
+
expiration: strictObject({
|
|
3582
|
+
maxEntries: number().optional(),
|
|
3583
|
+
maxAgeSeconds: number().optional()
|
|
3584
|
+
}).optional(),
|
|
3585
|
+
cacheableResponse: strictObject({
|
|
3586
|
+
statuses: array(number()).optional(),
|
|
3587
|
+
headers: record(string(), string()).optional()
|
|
3588
|
+
}).optional()
|
|
3589
|
+
}).optional()
|
|
3590
|
+
});
|
|
3591
|
+
const PwaIconSchema = strictObject({
|
|
3592
|
+
src: string(),
|
|
3593
|
+
sizes: string().optional(),
|
|
3594
|
+
type: string().optional(),
|
|
3595
|
+
purpose: string().optional()
|
|
3596
|
+
});
|
|
3597
|
+
const PwaFileHandlerSchema = strictObject({
|
|
3598
|
+
accept: record(string(), array(string().regex(/^\./, "file extensions must start with '.'"))),
|
|
3599
|
+
icons: array(PwaIconSchema).optional(),
|
|
3600
|
+
launch_type: _enum(["single-client", "multiple-clients"]).optional()
|
|
3601
|
+
});
|
|
3602
|
+
const PwaConfigSchema = strictObject({
|
|
3603
|
+
manifest: strictObject({
|
|
3604
|
+
name: string().optional(),
|
|
3605
|
+
short_name: string().optional(),
|
|
3606
|
+
description: string().optional(),
|
|
3607
|
+
theme_color: string().optional(),
|
|
3608
|
+
background_color: string().optional(),
|
|
3609
|
+
display: _enum([
|
|
3610
|
+
"fullscreen",
|
|
3611
|
+
"standalone",
|
|
3612
|
+
"minimal-ui",
|
|
3613
|
+
"browser"
|
|
3614
|
+
]).optional(),
|
|
3615
|
+
start_url: string().optional(),
|
|
3616
|
+
scope: string().optional(),
|
|
3617
|
+
icons: array(PwaIconSchema).optional(),
|
|
3618
|
+
file_handlers: array(PwaFileHandlerSchema).optional(),
|
|
3619
|
+
launch_handler: strictObject({ client_mode: _enum([
|
|
3620
|
+
"auto",
|
|
3621
|
+
"focus-existing",
|
|
3622
|
+
"navigate-existing",
|
|
3623
|
+
"navigate-new"
|
|
3624
|
+
]) }).optional()
|
|
3625
|
+
}).optional(),
|
|
3626
|
+
globPatterns: array(string()).optional(),
|
|
3627
|
+
globIgnores: array(string()).optional(),
|
|
3628
|
+
maximumFileSizeToCacheInBytes: number().optional(),
|
|
3629
|
+
runtimeCaching: array(PwaRuntimeCachingSchema).optional(),
|
|
3630
|
+
navigateFallbackDenylist: array(PwaUrlPatternSchema).optional()
|
|
3631
|
+
});
|
|
3447
3632
|
object({
|
|
3448
3633
|
name: string(),
|
|
3449
3634
|
description: string().optional(),
|
|
3450
3635
|
category: string().optional(),
|
|
3636
|
+
image: string().optional(),
|
|
3451
3637
|
publisher: PublisherSchema.optional(),
|
|
3452
3638
|
documentModels: PowerhouseModulesSchema,
|
|
3453
3639
|
apps: PowerhouseModulesSchema,
|
|
3454
3640
|
editors: PowerhouseModulesSchema,
|
|
3455
3641
|
processors: PowerhouseModulesSchema,
|
|
3456
3642
|
subgraphs: PowerhouseModulesSchema,
|
|
3457
|
-
config: array(ConfigEntrySchema).optional()
|
|
3643
|
+
config: array(ConfigEntrySchema).optional(),
|
|
3644
|
+
pwa: PwaConfigSchema.optional()
|
|
3458
3645
|
});
|
|
3459
3646
|
/**
|
|
3460
3647
|
* Cancels the last `count` operations.
|
|
@@ -3725,6 +3912,189 @@ const actions = {
|
|
|
3725
3912
|
...baseActions,
|
|
3726
3913
|
...documentModelActions
|
|
3727
3914
|
};
|
|
3915
|
+
const documentModelDocumentType = "powerhouse/document-model";
|
|
3916
|
+
/**
|
|
3917
|
+
* Thrown when a grant violates the v1 validation rules. The message is stored
|
|
3918
|
+
* on error operations, so it must be a pure function of the input.
|
|
3919
|
+
*/
|
|
3920
|
+
var InvalidGrantError = class extends Error {
|
|
3921
|
+
grantId;
|
|
3922
|
+
constructor(grantId, problem) {
|
|
3923
|
+
super(`Invalid grant "${grantId}": ${problem}`);
|
|
3924
|
+
this.name = "InvalidGrantError";
|
|
3925
|
+
this.grantId = grantId;
|
|
3926
|
+
}
|
|
3927
|
+
};
|
|
3928
|
+
/** Thrown for a `{ group }` principal on a group document: references never chain. */
|
|
3929
|
+
var GroupPrincipalNotAllowedError = class extends Error {
|
|
3930
|
+
grantId;
|
|
3931
|
+
constructor(grantId) {
|
|
3932
|
+
super(`Grant "${grantId}" uses a group principal on a group document: a group's auth scope cannot reference other groups`);
|
|
3933
|
+
this.name = "GroupPrincipalNotAllowedError";
|
|
3934
|
+
this.grantId = grantId;
|
|
3935
|
+
}
|
|
3936
|
+
};
|
|
3937
|
+
const GRANT_KEYS = new Set([
|
|
3938
|
+
"id",
|
|
3939
|
+
"description",
|
|
3940
|
+
"effect",
|
|
3941
|
+
"principal",
|
|
3942
|
+
"capability",
|
|
3943
|
+
"where"
|
|
3944
|
+
]);
|
|
3945
|
+
const PRINCIPAL_KINDS = new Set([
|
|
3946
|
+
"anyone",
|
|
3947
|
+
"address",
|
|
3948
|
+
"group",
|
|
3949
|
+
"match"
|
|
3950
|
+
]);
|
|
3951
|
+
const COMPARISON_CONDITION_KINDS = new Set([
|
|
3952
|
+
"eq",
|
|
3953
|
+
"ne",
|
|
3954
|
+
"lt",
|
|
3955
|
+
"lte",
|
|
3956
|
+
"gt",
|
|
3957
|
+
"gte"
|
|
3958
|
+
]);
|
|
3959
|
+
function isPlainValue(value) {
|
|
3960
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3961
|
+
}
|
|
3962
|
+
function operandProblem(value, capabilityScope, budget) {
|
|
3963
|
+
budget.nodes -= 1;
|
|
3964
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
3965
|
+
if (!isPlainValue(value)) return "operand must be an object";
|
|
3966
|
+
const keys = Object.keys(value);
|
|
3967
|
+
if (keys.length !== 1) return "operand must have exactly one of attr or lit";
|
|
3968
|
+
if (keys[0] === "attr") {
|
|
3969
|
+
const attr = value.attr;
|
|
3970
|
+
if (typeof attr !== "string" || attr.length === 0) return "attr must be a non-empty string";
|
|
3971
|
+
if (capabilityScope !== void 0 && capabilityScope !== "*" && attr.startsWith("doc.")) {
|
|
3972
|
+
const pathScope = attr.split(".")[1] ?? "";
|
|
3973
|
+
if (pathScope !== capabilityScope) return `condition path "${attr}" reads scope "${pathScope}" but the capability covers only scope "${capabilityScope}"`;
|
|
3974
|
+
}
|
|
3975
|
+
return null;
|
|
3976
|
+
}
|
|
3977
|
+
if (keys[0] === "lit") {
|
|
3978
|
+
const lit = value.lit;
|
|
3979
|
+
if (lit !== null && typeof lit !== "string" && typeof lit !== "number" && typeof lit !== "boolean") return "lit must be a string, number, boolean, or null";
|
|
3980
|
+
if (typeof lit === "number" && !Number.isFinite(lit)) return "lit must be a finite number";
|
|
3981
|
+
if (typeof lit === "number" && Object.is(lit, -0)) return "lit must not be negative zero";
|
|
3982
|
+
return null;
|
|
3983
|
+
}
|
|
3984
|
+
return `unknown operand kind "${keys[0]}"`;
|
|
3985
|
+
}
|
|
3986
|
+
function conditionProblem(value, capabilityScope, depth, budget) {
|
|
3987
|
+
if (depth > 10) return `condition exceeds depth 10`;
|
|
3988
|
+
budget.nodes -= 1;
|
|
3989
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
3990
|
+
if (!isPlainValue(value)) return "condition must be an object";
|
|
3991
|
+
const keys = Object.keys(value);
|
|
3992
|
+
if (keys.length !== 1) return "condition must have exactly one operator";
|
|
3993
|
+
const kind = keys[0];
|
|
3994
|
+
const body = value[kind];
|
|
3995
|
+
if (COMPARISON_CONDITION_KINDS.has(kind)) {
|
|
3996
|
+
if (!Array.isArray(body) || body.length !== 2) return `${kind} requires a pair of operands`;
|
|
3997
|
+
for (const operand of body) {
|
|
3998
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
3999
|
+
if (problem !== null) return problem;
|
|
4000
|
+
}
|
|
4001
|
+
return null;
|
|
4002
|
+
}
|
|
4003
|
+
if (kind === "in" || kind === "notIn") {
|
|
4004
|
+
if (!Array.isArray(body) || body.length !== 2 || !Array.isArray(body[1])) return `${kind} requires an operand and an operand list`;
|
|
4005
|
+
const first = operandProblem(body[0], capabilityScope, budget);
|
|
4006
|
+
if (first !== null) return first;
|
|
4007
|
+
for (const operand of body[1]) {
|
|
4008
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
4009
|
+
if (problem !== null) return problem;
|
|
4010
|
+
}
|
|
4011
|
+
return null;
|
|
4012
|
+
}
|
|
4013
|
+
if (kind === "exists") return operandProblem(body, capabilityScope, budget);
|
|
4014
|
+
if (kind === "and" || kind === "or") {
|
|
4015
|
+
if (!Array.isArray(body)) return `${kind} requires a condition list`;
|
|
4016
|
+
for (const child of body) {
|
|
4017
|
+
const problem = conditionProblem(child, capabilityScope, depth + 1, budget);
|
|
4018
|
+
if (problem !== null) return problem;
|
|
4019
|
+
}
|
|
4020
|
+
return null;
|
|
4021
|
+
}
|
|
4022
|
+
if (kind === "not") return conditionProblem(body, capabilityScope, depth + 1, budget);
|
|
4023
|
+
return `unknown condition operator "${kind}"`;
|
|
4024
|
+
}
|
|
4025
|
+
function principalProblem(value, capabilityScope) {
|
|
4026
|
+
if (!isPlainValue(value)) return "principal must be an object";
|
|
4027
|
+
const keys = Object.keys(value);
|
|
4028
|
+
if (keys.length !== 1 || !PRINCIPAL_KINDS.has(keys[0])) return "principal must have exactly one of anyone, address, group, or match";
|
|
4029
|
+
const kind = keys[0];
|
|
4030
|
+
if (kind === "anyone" && value.anyone !== true) return "anyone must be true";
|
|
4031
|
+
if (kind === "address") {
|
|
4032
|
+
const address = value.address;
|
|
4033
|
+
if (typeof address !== "string" || address.length === 0) return "address must be a non-empty string";
|
|
4034
|
+
}
|
|
4035
|
+
if (kind === "group") {
|
|
4036
|
+
const group = value.group;
|
|
4037
|
+
if (typeof group !== "string" || group.length === 0) return "group must be a non-empty string";
|
|
4038
|
+
}
|
|
4039
|
+
if (kind === "match") return conditionProblem(value.match, capabilityScope, 1, { nodes: 100 });
|
|
4040
|
+
return null;
|
|
4041
|
+
}
|
|
4042
|
+
function capabilityProblem(value) {
|
|
4043
|
+
if (!isPlainValue(value)) return "capability must be an object";
|
|
4044
|
+
const can = value.can;
|
|
4045
|
+
if (can !== "read" && can !== "execute") return "capability.can must be read or execute";
|
|
4046
|
+
const allowedKeys = can === "execute" ? [
|
|
4047
|
+
"can",
|
|
4048
|
+
"scope",
|
|
4049
|
+
"operation"
|
|
4050
|
+
] : ["can", "scope"];
|
|
4051
|
+
const unknownKeys = Object.keys(value).filter((key) => !allowedKeys.includes(key)).sort();
|
|
4052
|
+
if (unknownKeys.length > 0) return `unknown capability key "${unknownKeys[0]}"`;
|
|
4053
|
+
if (value.scope !== void 0) {
|
|
4054
|
+
if (typeof value.scope !== "string" || value.scope.length === 0) return "capability.scope must be a non-empty string";
|
|
4055
|
+
}
|
|
4056
|
+
if (can === "execute" && value.operation !== void 0) {
|
|
4057
|
+
const operation = value.operation;
|
|
4058
|
+
if (!Array.isArray(operation)) return "capability.operation must be an array";
|
|
4059
|
+
if (operation.length > 100) return `capability.operation exceeds 100 entries`;
|
|
4060
|
+
for (const entry of operation) if (typeof entry !== "string" || entry.length === 0) return "capability.operation entries must be non-empty strings";
|
|
4061
|
+
}
|
|
4062
|
+
return null;
|
|
4063
|
+
}
|
|
4064
|
+
/** Returns the first v1-rule violation, or null. Pure, total, deterministic. */
|
|
4065
|
+
function grantProblem(value) {
|
|
4066
|
+
if (!isPlainValue(value)) return "grant must be an object";
|
|
4067
|
+
const unknownKeys = Object.keys(value).filter((key) => !GRANT_KEYS.has(key)).sort();
|
|
4068
|
+
if (unknownKeys.length > 0) return `unknown grant key "${unknownKeys[0]}"`;
|
|
4069
|
+
if (typeof value.id !== "string" || value.id.length === 0) return "id must be a non-empty string";
|
|
4070
|
+
if (typeof value.description !== "string") return "description must be a string";
|
|
4071
|
+
if (value.effect !== "allow" && value.effect !== "deny") return "effect must be allow or deny";
|
|
4072
|
+
const capabilityValue = value.capability;
|
|
4073
|
+
const capability = capabilityProblem(capabilityValue);
|
|
4074
|
+
if (capability !== null) return capability;
|
|
4075
|
+
const capabilityScope = capabilityValue.scope;
|
|
4076
|
+
const principal = principalProblem(value.principal, capabilityScope);
|
|
4077
|
+
if (principal !== null) return principal;
|
|
4078
|
+
if (value.where !== void 0) return conditionProblem(value.where, capabilityScope, 1, { nodes: 100 });
|
|
4079
|
+
return null;
|
|
4080
|
+
}
|
|
4081
|
+
/** V1 shape rules plus the group-document group-principal ban. */
|
|
4082
|
+
function assertValidGrant(grant, documentType) {
|
|
4083
|
+
const grantId = isPlainValue(grant) && typeof grant.id === "string" ? grant.id : "";
|
|
4084
|
+
const problem = grantProblem(grant);
|
|
4085
|
+
if (problem !== null) throw new InvalidGrantError(grantId, problem);
|
|
4086
|
+
if (documentType === "@powerhousedao/document-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
|
|
4087
|
+
}
|
|
4088
|
+
/** Validates an initial grant list: the count cap plus every grant. */
|
|
4089
|
+
function assertValidInitialGrants(grants, documentType) {
|
|
4090
|
+
if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
|
|
4091
|
+
for (const grant of grants) assertValidGrant(grant, documentType);
|
|
4092
|
+
}
|
|
4093
|
+
/** Validates a grant upsert: the grant itself plus the count cap on append. */
|
|
4094
|
+
function assertValidGrantUpsert(grant, existing, documentType) {
|
|
4095
|
+
assertValidGrant(grant, documentType);
|
|
4096
|
+
if (!existing.some((g) => g.id === grant.id) && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
|
|
4097
|
+
}
|
|
3728
4098
|
const documentModelFileExtension = "phdm";
|
|
3729
4099
|
const documentModelInitialLocalState = {};
|
|
3730
4100
|
const documentModelInitialGlobalState = {
|
|
@@ -4306,7 +4676,252 @@ const documentModelGlobalState = {
|
|
|
4306
4676
|
};
|
|
4307
4677
|
const HASH_ALGORITHM_SHA1 = "sha1";
|
|
4308
4678
|
const HASH_ENCODING_BASE64 = "base64";
|
|
4309
|
-
|
|
4679
|
+
/**
|
|
4680
|
+
* Creates a default PHAuthState
|
|
4681
|
+
*/
|
|
4682
|
+
function defaultAuthState() {
|
|
4683
|
+
return {
|
|
4684
|
+
version: 0,
|
|
4685
|
+
grants: []
|
|
4686
|
+
};
|
|
4687
|
+
}
|
|
4688
|
+
/**
|
|
4689
|
+
* Creates a default PHDocumentState
|
|
4690
|
+
*/
|
|
4691
|
+
function defaultDocumentState() {
|
|
4692
|
+
return {
|
|
4693
|
+
version: 0,
|
|
4694
|
+
hash: {
|
|
4695
|
+
algorithm: HASH_ALGORITHM_SHA1,
|
|
4696
|
+
encoding: HASH_ENCODING_BASE64
|
|
4697
|
+
}
|
|
4698
|
+
};
|
|
4699
|
+
}
|
|
4700
|
+
/**
|
|
4701
|
+
* Creates a default PHBaseState with auth and document properties
|
|
4702
|
+
*/
|
|
4703
|
+
function defaultBaseState() {
|
|
4704
|
+
return {
|
|
4705
|
+
auth: defaultAuthState(),
|
|
4706
|
+
document: defaultDocumentState()
|
|
4707
|
+
};
|
|
4708
|
+
}
|
|
4709
|
+
/**
|
|
4710
|
+
* Creates a PHAuthState with the given properties
|
|
4711
|
+
*/
|
|
4712
|
+
function createAuthState(auth) {
|
|
4713
|
+
return {
|
|
4714
|
+
...defaultAuthState(),
|
|
4715
|
+
...auth
|
|
4716
|
+
};
|
|
4717
|
+
}
|
|
4718
|
+
/**
|
|
4719
|
+
* Creates a PHDocumentState with the given properties
|
|
4720
|
+
*/
|
|
4721
|
+
function createDocumentState(document) {
|
|
4722
|
+
return {
|
|
4723
|
+
...defaultDocumentState(),
|
|
4724
|
+
...document
|
|
4725
|
+
};
|
|
4726
|
+
}
|
|
4727
|
+
/**
|
|
4728
|
+
* Creates a PHBaseState with the given auth and document properties
|
|
4729
|
+
*/
|
|
4730
|
+
function createBaseState(auth, document) {
|
|
4731
|
+
return {
|
|
4732
|
+
auth: createAuthState(auth),
|
|
4733
|
+
document: createDocumentState(document)
|
|
4734
|
+
};
|
|
4735
|
+
}
|
|
4736
|
+
/**
|
|
4737
|
+
* Backfills the auth scope to the default for legacy documents serialized with
|
|
4738
|
+
* an empty `auth`. Replaces only `state.auth`. Idempotent.
|
|
4739
|
+
*/
|
|
4740
|
+
function backfillAuthState(state) {
|
|
4741
|
+
return {
|
|
4742
|
+
...state,
|
|
4743
|
+
auth: createAuthState(state.auth)
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
4746
|
+
function defaultGlobalState() {
|
|
4747
|
+
return {
|
|
4748
|
+
...defaultBaseState(),
|
|
4749
|
+
author: {
|
|
4750
|
+
name: "",
|
|
4751
|
+
website: ""
|
|
4752
|
+
},
|
|
4753
|
+
description: "",
|
|
4754
|
+
extension: "",
|
|
4755
|
+
id: "",
|
|
4756
|
+
name: "",
|
|
4757
|
+
specifications: []
|
|
4758
|
+
};
|
|
4759
|
+
}
|
|
4760
|
+
function defaultLocalState() {
|
|
4761
|
+
return {};
|
|
4762
|
+
}
|
|
4763
|
+
function createGlobalState(state) {
|
|
4764
|
+
return {
|
|
4765
|
+
...defaultGlobalState(),
|
|
4766
|
+
...state || {}
|
|
4767
|
+
};
|
|
4768
|
+
}
|
|
4769
|
+
function createLocalState(state) {
|
|
4770
|
+
return {
|
|
4771
|
+
...defaultLocalState(),
|
|
4772
|
+
...state || {}
|
|
4773
|
+
};
|
|
4774
|
+
}
|
|
4775
|
+
function createState(baseState, globalState, localState) {
|
|
4776
|
+
return {
|
|
4777
|
+
...createBaseState(baseState?.auth, baseState?.document),
|
|
4778
|
+
global: createGlobalState(globalState),
|
|
4779
|
+
local: createLocalState(localState)
|
|
4780
|
+
};
|
|
4781
|
+
}
|
|
4782
|
+
/**
|
|
4783
|
+
* Destructuring a null input (reachable via raw synced operations) would
|
|
4784
|
+
* store an engine-specific TypeError message on the error operation.
|
|
4785
|
+
*/
|
|
4786
|
+
function assertActionInputShape(input) {
|
|
4787
|
+
if (!isPlainValue(input)) throw new InvalidActionInputError({ input: "must be an object" });
|
|
4788
|
+
}
|
|
4789
|
+
function withGrants(document, grants) {
|
|
4790
|
+
return {
|
|
4791
|
+
...document,
|
|
4792
|
+
state: {
|
|
4793
|
+
...document.state,
|
|
4794
|
+
auth: {
|
|
4795
|
+
...document.state.auth,
|
|
4796
|
+
grants
|
|
4797
|
+
}
|
|
4798
|
+
}
|
|
4799
|
+
};
|
|
4800
|
+
}
|
|
4801
|
+
const P256_PUBKEY_MULTICODEC = [128, 36];
|
|
4802
|
+
const DID_KEY_PREFIX = "did:key:z";
|
|
4803
|
+
function bytesEqual(a, b) {
|
|
4804
|
+
if (a.length !== b.length) return false;
|
|
4805
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
4806
|
+
return true;
|
|
4807
|
+
}
|
|
4808
|
+
/**
|
|
4809
|
+
* True when `signerKey` (an ActionSigner app key, a did:key) identifies the same
|
|
4810
|
+
* key recorded as the document creator. Returns false
|
|
4811
|
+
* when there is no creator (empty JWK) or no signer key.
|
|
4812
|
+
*/
|
|
4813
|
+
function isDocumentCreator(creatorKey, signerKey) {
|
|
4814
|
+
if (!creatorKey?.x || !creatorKey.y) return false;
|
|
4815
|
+
if (!signerKey || !signerKey.startsWith(DID_KEY_PREFIX)) return false;
|
|
4816
|
+
const decoded = base58Decode(signerKey.slice(9));
|
|
4817
|
+
if (!decoded || decoded.length !== 35) return false;
|
|
4818
|
+
if (decoded[0] !== P256_PUBKEY_MULTICODEC[0] || decoded[1] !== P256_PUBKEY_MULTICODEC[1]) return false;
|
|
4819
|
+
const parityPrefix = decoded[2];
|
|
4820
|
+
if (parityPrefix !== 2 && parityPrefix !== 3) return false;
|
|
4821
|
+
const didX = decoded.subarray(3, 35);
|
|
4822
|
+
const jwkX = base64UrlToBytes(creatorKey.x);
|
|
4823
|
+
const jwkY = base64UrlToBytes(creatorKey.y);
|
|
4824
|
+
if (jwkX.length !== 32 || jwkY.length !== 32) return false;
|
|
4825
|
+
if (!bytesEqual(didX, jwkX)) return false;
|
|
4826
|
+
return (jwkY[31] & 1) === 1 === (parityPrefix === 3);
|
|
4827
|
+
}
|
|
4828
|
+
/**
|
|
4829
|
+
* Sets the initial policy. Valid only while the auth scope is uninitialized
|
|
4830
|
+
* (version 0). The input version is the policy language version and must be an
|
|
4831
|
+
* integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
|
|
4832
|
+
* document it must be signed by the document creator (`header.sig.publicKey`).
|
|
4833
|
+
*/
|
|
4834
|
+
function applyInitializeAuthAction(document, action) {
|
|
4835
|
+
assertActionInputShape(action.input);
|
|
4836
|
+
const { version, grants } = action.input;
|
|
4837
|
+
if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
|
|
4838
|
+
if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
|
|
4839
|
+
if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
4840
|
+
assertValidInitialGrants(grants, document.header.documentType);
|
|
4841
|
+
const creatorKey = document.header.sig.publicKey;
|
|
4842
|
+
const signerKey = action.context?.signer?.app.key;
|
|
4843
|
+
const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
|
|
4844
|
+
if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
|
|
4845
|
+
const creator = hasCreator ? signerKey : void 0;
|
|
4846
|
+
return {
|
|
4847
|
+
...document,
|
|
4848
|
+
state: {
|
|
4849
|
+
...document.state,
|
|
4850
|
+
auth: createAuthState(creator ? {
|
|
4851
|
+
version,
|
|
4852
|
+
grants,
|
|
4853
|
+
creator
|
|
4854
|
+
} : {
|
|
4855
|
+
version,
|
|
4856
|
+
grants
|
|
4857
|
+
})
|
|
4858
|
+
}
|
|
4859
|
+
};
|
|
4860
|
+
}
|
|
4861
|
+
/** Upserts a grant by id: replaces in place if present, otherwise appends. */
|
|
4862
|
+
function applySetGrantAction(document, action) {
|
|
4863
|
+
assertActionInputShape(action.input);
|
|
4864
|
+
const { grant } = action.input;
|
|
4865
|
+
const grants = document.state.auth.grants;
|
|
4866
|
+
assertValidGrantUpsert(grant, grants, document.header.documentType);
|
|
4867
|
+
return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
|
|
4868
|
+
}
|
|
4869
|
+
/** Removes a grant by id; throws if the id is not present. */
|
|
4870
|
+
function applyRemoveGrantAction(document, action) {
|
|
4871
|
+
assertActionInputShape(action.input);
|
|
4872
|
+
const { id } = action.input;
|
|
4873
|
+
const grants = document.state.auth.grants;
|
|
4874
|
+
if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
|
|
4875
|
+
return withGrants(document, grants.filter((g) => g.id !== id));
|
|
4876
|
+
}
|
|
4877
|
+
/**
|
|
4878
|
+
* Moves a grant by id to a new index. Order is load-bearing (the last
|
|
4879
|
+
* applicable grant wins), so the relative order of the other grants is kept.
|
|
4880
|
+
* The target index is clamped to the valid range; an unknown id throws.
|
|
4881
|
+
*/
|
|
4882
|
+
function applyMoveGrantAction(document, action) {
|
|
4883
|
+
assertActionInputShape(action.input);
|
|
4884
|
+
const { id, index } = action.input;
|
|
4885
|
+
const grants = document.state.auth.grants;
|
|
4886
|
+
const from = grants.findIndex((g) => g.id === id);
|
|
4887
|
+
if (from === -1) throw new GrantNotFoundError(id);
|
|
4888
|
+
const next = [...grants];
|
|
4889
|
+
const [moved] = next.splice(from, 1);
|
|
4890
|
+
const to = Math.max(0, Math.min(index, next.length));
|
|
4891
|
+
next.splice(to, 0, moved);
|
|
4892
|
+
return withGrants(document, next);
|
|
4893
|
+
}
|
|
4894
|
+
/**
|
|
4895
|
+
* Dispatches an auth-scope action to its handler. This is the auth scope's
|
|
4896
|
+
* dedicated reducer: it is applied by the base reducer instead of the model
|
|
4897
|
+
* reducer, mirroring the document-scope platform handlers. Unknown types are a
|
|
4898
|
+
* no-op, matching the model-reducer default.
|
|
4899
|
+
*/
|
|
4900
|
+
function applyAuthAction(document, action) {
|
|
4901
|
+
switch (action.type) {
|
|
4902
|
+
case "INITIALIZE_AUTH": return applyInitializeAuthAction(document, action);
|
|
4903
|
+
case "SET_GRANT": return applySetGrantAction(document, action);
|
|
4904
|
+
case "REMOVE_GRANT": return applyRemoveGrantAction(document, action);
|
|
4905
|
+
case "MOVE_GRANT": return applyMoveGrantAction(document, action);
|
|
4906
|
+
default: return document;
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
/**
|
|
4910
|
+
* Because only creators can initialize auth scopes, we must verify that either
|
|
4911
|
+
* the document has no auth or the version and creator match.
|
|
4912
|
+
*/
|
|
4913
|
+
function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
|
|
4914
|
+
if (!source || source.version === 0) return;
|
|
4915
|
+
if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
|
|
4916
|
+
}
|
|
4917
|
+
/** UNDO, REDO and PRUNE are rejected on the auth scope. */
|
|
4918
|
+
function assertAuthScopeActionAllowed(action) {
|
|
4919
|
+
if (action.scope === "auth" && [
|
|
4920
|
+
"UNDO",
|
|
4921
|
+
"REDO",
|
|
4922
|
+
"PRUNE"
|
|
4923
|
+
].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
|
|
4924
|
+
}
|
|
4310
4925
|
const BaseDocumentHeaderSchema = object({
|
|
4311
4926
|
id: string(),
|
|
4312
4927
|
name: string(),
|
|
@@ -4437,6 +5052,7 @@ function createDocumentScopeOperations(header, state) {
|
|
|
4437
5052
|
function baseCreateDocument(createState, initialState, documentType = "") {
|
|
4438
5053
|
const state = createState(initialState);
|
|
4439
5054
|
const header = createPresignedHeader(generateId(), documentType);
|
|
5055
|
+
header.protocolVersions = { "base-reducer": 2 };
|
|
4440
5056
|
return {
|
|
4441
5057
|
header,
|
|
4442
5058
|
state,
|
|
@@ -4460,6 +5076,18 @@ function hashDocumentStateForScope(document, scope = "global") {
|
|
|
4460
5076
|
* Uses the V2 model where consecutive NOOPs form chains.
|
|
4461
5077
|
* Unlike V1 garbageCollect, this preserves ALL operations but marks which to apply.
|
|
4462
5078
|
*/
|
|
5079
|
+
/**
|
|
5080
|
+
* The base-reducer protocol version a document is written against. Every
|
|
5081
|
+
* document carries one, set from the CREATE_DOCUMENT input. A header without
|
|
5082
|
+
* one was built outside that path, and choosing a version on its behalf would
|
|
5083
|
+
* replay the document through a reducer it was not written for, so it is an
|
|
5084
|
+
* error rather than a default.
|
|
5085
|
+
*/
|
|
5086
|
+
function baseReducerVersion(header) {
|
|
5087
|
+
const version = header.protocolVersions?.["base-reducer"];
|
|
5088
|
+
if (typeof version !== "number") throw new Error(`Document ${header.id} carries no base-reducer protocol version`);
|
|
5089
|
+
return version;
|
|
5090
|
+
}
|
|
4463
5091
|
function garbageCollectV2(sortedOperations) {
|
|
4464
5092
|
const result = [];
|
|
4465
5093
|
let noopChainLength = 0;
|
|
@@ -4478,7 +5106,8 @@ const defaultCreateState = (state) => {
|
|
|
4478
5106
|
};
|
|
4479
5107
|
function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
|
|
4480
5108
|
const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
|
|
4481
|
-
|
|
5109
|
+
const backfilledInitialState = backfillAuthState(initialState);
|
|
5110
|
+
let documentState = backfilledInitialState;
|
|
4482
5111
|
const operationsToReplay = [];
|
|
4483
5112
|
const allScopes = new Set([
|
|
4484
5113
|
...Object.keys(operations),
|
|
@@ -4513,7 +5142,7 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
|
|
|
4513
5142
|
const document = {
|
|
4514
5143
|
header,
|
|
4515
5144
|
state: defaultCreateState(documentState),
|
|
4516
|
-
initialState,
|
|
5145
|
+
initialState: backfilledInitialState,
|
|
4517
5146
|
operations: initialOperations,
|
|
4518
5147
|
clipboard: []
|
|
4519
5148
|
};
|
|
@@ -4806,7 +5435,7 @@ function loadStateOperation(document, action) {
|
|
|
4806
5435
|
...document.header,
|
|
4807
5436
|
name: action.state.name
|
|
4808
5437
|
},
|
|
4809
|
-
state: action.state.data
|
|
5438
|
+
state: backfillAuthState(action.state.data)
|
|
4810
5439
|
};
|
|
4811
5440
|
}
|
|
4812
5441
|
function replayOperations(initialState, clearedOperations, stateReducer, header, dispatch, documentReducer = baseReducer, skipHeaderOperations = {}, options) {
|
|
@@ -4980,6 +5609,7 @@ function processUndoOperation(document, scope, customReducer, reuseOperationResu
|
|
|
4980
5609
|
function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
4981
5610
|
const { skip, ignoreSkipOperations = false, reuseOperationResultingState = false, operationResultingStateParser, pruneOnSkip = true, branch = "main" } = options;
|
|
4982
5611
|
let _action = actionFromAction(action);
|
|
5612
|
+
assertAuthScopeActionAllowed(_action);
|
|
4983
5613
|
let skipValue = skip ?? options.replayOptions?.operation.skip ?? 0;
|
|
4984
5614
|
let newDocument = { ...document };
|
|
4985
5615
|
let reuseLastOperationIndex = false;
|
|
@@ -5027,6 +5657,13 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
|
5027
5657
|
}
|
|
5028
5658
|
newDocument = create(newDocument, (draft) => {
|
|
5029
5659
|
try {
|
|
5660
|
+
if (_action.scope === "auth") {
|
|
5661
|
+
const authState = applyAuthAction(newDocument, _action).state;
|
|
5662
|
+
unsafe(() => {
|
|
5663
|
+
draft.state = castDraft(authState);
|
|
5664
|
+
});
|
|
5665
|
+
return;
|
|
5666
|
+
}
|
|
5030
5667
|
const newState = customReducer(draft.state, _action, dispatch);
|
|
5031
5668
|
if (newState) unsafe(() => {
|
|
5032
5669
|
draft.state = castDraft(newState);
|
|
@@ -5820,10 +6457,10 @@ function applyInitialState(document, action) {
|
|
|
5820
6457
|
const input = action.input;
|
|
5821
6458
|
const newState = input.initialState || input.state;
|
|
5822
6459
|
if (newState) {
|
|
5823
|
-
document.state = {
|
|
6460
|
+
document.state = backfillAuthState({
|
|
5824
6461
|
...document.state,
|
|
5825
6462
|
...newState
|
|
5826
|
-
};
|
|
6463
|
+
});
|
|
5827
6464
|
document.initialState = document.state;
|
|
5828
6465
|
}
|
|
5829
6466
|
}
|
|
@@ -5883,7 +6520,6 @@ function computeUpgradeTransitions(manifest, fromVersion, toVersion) {
|
|
|
5883
6520
|
}
|
|
5884
6521
|
return transitions;
|
|
5885
6522
|
}
|
|
5886
|
-
const NON_DOMAIN_SCOPES$1 = new Set(["auth", "document"]);
|
|
5887
6523
|
function highestReducerVersion(reducers) {
|
|
5888
6524
|
const keys = Object.keys(reducers).map(Number);
|
|
5889
6525
|
if (keys.length === 0) throw new Error("VersionedReplayConfig.reducers must not be empty");
|
|
@@ -5911,15 +6547,15 @@ function highestReducerVersion(reducers) {
|
|
|
5911
6547
|
*/
|
|
5912
6548
|
function replayDocumentVersioned(initialState, operations, config, header, dispatch, options) {
|
|
5913
6549
|
const { checkHashes = true, skipIndexValidation } = options || {};
|
|
5914
|
-
const protocolVersion = header
|
|
6550
|
+
const protocolVersion = baseReducerVersion(header);
|
|
5915
6551
|
const spine = (operations["document"] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
5916
6552
|
const upgrades = spine.filter((op) => op.action.type === "UPGRADE_DOCUMENT");
|
|
5917
6553
|
const legacyFallback = () => {
|
|
5918
|
-
const
|
|
6554
|
+
const replayOps = Object.fromEntries(Object.entries(operations).filter(([s]) => s !== "document"));
|
|
5919
6555
|
const latestVersion = highestReducerVersion(config.reducers);
|
|
5920
6556
|
const reducer = config.reducers[latestVersion];
|
|
5921
6557
|
return {
|
|
5922
|
-
...replayDocument(initialState,
|
|
6558
|
+
...replayDocument(initialState, replayOps, reducer, header, dispatch, {}, options),
|
|
5923
6559
|
operations
|
|
5924
6560
|
};
|
|
5925
6561
|
};
|
|
@@ -5943,14 +6579,14 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5943
6579
|
const a = op.action;
|
|
5944
6580
|
return a.input.fromVersion > 0 && a.input.fromVersion < a.input.toVersion;
|
|
5945
6581
|
});
|
|
5946
|
-
const
|
|
6582
|
+
const replayScopes = Object.keys(operations).filter((s) => s !== "document");
|
|
5947
6583
|
const scopeOps = {};
|
|
5948
|
-
for (const s of
|
|
6584
|
+
for (const s of replayScopes) scopeOps[s] = (operations[s] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
5949
6585
|
const boundaries = validatedUpgrades.map((upgradeOp) => {
|
|
5950
6586
|
const revisionSnapshot = upgradeOp.action.input.revision;
|
|
5951
6587
|
const upgradeTimestamp = upgradeOp.timestampUtcMs;
|
|
5952
6588
|
const boundary = {};
|
|
5953
|
-
for (const s of
|
|
6589
|
+
for (const s of replayScopes) {
|
|
5954
6590
|
const ops = scopeOps[s] ?? [];
|
|
5955
6591
|
if (revisionSnapshot !== void 0) {
|
|
5956
6592
|
const rev = revisionSnapshot[s] ?? 0;
|
|
@@ -5968,7 +6604,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5968
6604
|
}
|
|
5969
6605
|
return boundary;
|
|
5970
6606
|
});
|
|
5971
|
-
for (let i = 1; i < boundaries.length; i++) for (const s of
|
|
6607
|
+
for (let i = 1; i < boundaries.length; i++) for (const s of replayScopes) {
|
|
5972
6608
|
const prev = boundaries[i - 1]?.[s] ?? 0;
|
|
5973
6609
|
const curr = boundaries[i]?.[s] ?? 0;
|
|
5974
6610
|
if (boundaries[i]) boundaries[i][s] = Math.max(prev, curr);
|
|
@@ -5980,10 +6616,11 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5980
6616
|
]);
|
|
5981
6617
|
const initialOperations = {};
|
|
5982
6618
|
for (const s of allScopes) initialOperations[s] = [];
|
|
6619
|
+
const backfilledSeed = backfillAuthState(seedState);
|
|
5983
6620
|
let document = {
|
|
5984
6621
|
header,
|
|
5985
|
-
state:
|
|
5986
|
-
initialState:
|
|
6622
|
+
state: backfilledSeed,
|
|
6623
|
+
initialState: backfilledSeed,
|
|
5987
6624
|
operations: initialOperations,
|
|
5988
6625
|
clipboard: []
|
|
5989
6626
|
};
|
|
@@ -5995,7 +6632,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
5995
6632
|
const available = Object.keys(config.reducers).join(", ");
|
|
5996
6633
|
throw new Error(`No reducer registered for document version ${currentVersion}. Available versions: ${available}`);
|
|
5997
6634
|
}
|
|
5998
|
-
for (const s of
|
|
6635
|
+
for (const s of replayScopes) {
|
|
5999
6636
|
const ops = scopeOps[s] ?? [];
|
|
6000
6637
|
const segStart = k === 0 ? 0 : boundaries[k - 1]?.[s] ?? 0;
|
|
6001
6638
|
const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
|
|
@@ -6048,7 +6685,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6048
6685
|
}
|
|
6049
6686
|
};
|
|
6050
6687
|
if (!checkHashes) {
|
|
6051
|
-
const allReplayedOps =
|
|
6688
|
+
const allReplayedOps = replayScopes.flatMap((s) => scopeOps[s] ?? []);
|
|
6052
6689
|
for (const scope of Object.keys(document.state)) {
|
|
6053
6690
|
const capturedHash = segmentEndHashPerScope.get(scope);
|
|
6054
6691
|
const scopeHash = capturedHash !== void 0 ? capturedHash : hashDocumentStateForScope(document, scope);
|
|
@@ -6090,7 +6727,6 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6090
6727
|
}
|
|
6091
6728
|
};
|
|
6092
6729
|
}
|
|
6093
|
-
const NON_DOMAIN_SCOPES = new Set(["auth", "document"]);
|
|
6094
6730
|
function zipAsync(data) {
|
|
6095
6731
|
return new Promise((resolve, reject) => {
|
|
6096
6732
|
zip(data, (err, out) => err ? reject(err) : resolve(out));
|
|
@@ -6169,7 +6805,7 @@ async function parseZipData(data) {
|
|
|
6169
6805
|
async function loadFromZipData(data, reducer, options) {
|
|
6170
6806
|
const { initialState, header, clearedOperations } = await parseZipData(data);
|
|
6171
6807
|
return {
|
|
6172
|
-
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) =>
|
|
6808
|
+
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) => scope !== "document")), reducer, header, void 0, {}, options),
|
|
6173
6809
|
operations: clearedOperations
|
|
6174
6810
|
};
|
|
6175
6811
|
}
|
|
@@ -6192,96 +6828,6 @@ const documentModelLoadFromInput = (input) => {
|
|
|
6192
6828
|
const documentModelSaveToFileHandle = (document, input) => {
|
|
6193
6829
|
return baseSaveToFileHandle(document, input);
|
|
6194
6830
|
};
|
|
6195
|
-
/**
|
|
6196
|
-
* Creates a default PHAuthState
|
|
6197
|
-
*/
|
|
6198
|
-
function defaultAuthState() {
|
|
6199
|
-
return {};
|
|
6200
|
-
}
|
|
6201
|
-
/**
|
|
6202
|
-
* Creates a default PHDocumentState
|
|
6203
|
-
*/
|
|
6204
|
-
function defaultDocumentState() {
|
|
6205
|
-
return {
|
|
6206
|
-
version: 0,
|
|
6207
|
-
hash: {
|
|
6208
|
-
algorithm: HASH_ALGORITHM_SHA1,
|
|
6209
|
-
encoding: HASH_ENCODING_BASE64
|
|
6210
|
-
}
|
|
6211
|
-
};
|
|
6212
|
-
}
|
|
6213
|
-
/**
|
|
6214
|
-
* Creates a default PHBaseState with auth and document properties
|
|
6215
|
-
*/
|
|
6216
|
-
function defaultBaseState() {
|
|
6217
|
-
return {
|
|
6218
|
-
auth: defaultAuthState(),
|
|
6219
|
-
document: defaultDocumentState()
|
|
6220
|
-
};
|
|
6221
|
-
}
|
|
6222
|
-
/**
|
|
6223
|
-
* Creates a PHAuthState with the given properties
|
|
6224
|
-
*/
|
|
6225
|
-
function createAuthState(auth) {
|
|
6226
|
-
return {
|
|
6227
|
-
...defaultAuthState(),
|
|
6228
|
-
...auth
|
|
6229
|
-
};
|
|
6230
|
-
}
|
|
6231
|
-
/**
|
|
6232
|
-
* Creates a PHDocumentState with the given properties
|
|
6233
|
-
*/
|
|
6234
|
-
function createDocumentState(document) {
|
|
6235
|
-
return {
|
|
6236
|
-
...defaultDocumentState(),
|
|
6237
|
-
...document
|
|
6238
|
-
};
|
|
6239
|
-
}
|
|
6240
|
-
/**
|
|
6241
|
-
* Creates a PHBaseState with the given auth and document properties
|
|
6242
|
-
*/
|
|
6243
|
-
function createBaseState(auth, document) {
|
|
6244
|
-
return {
|
|
6245
|
-
auth: createAuthState(auth),
|
|
6246
|
-
document: createDocumentState(document)
|
|
6247
|
-
};
|
|
6248
|
-
}
|
|
6249
|
-
function defaultGlobalState() {
|
|
6250
|
-
return {
|
|
6251
|
-
...defaultBaseState(),
|
|
6252
|
-
author: {
|
|
6253
|
-
name: "",
|
|
6254
|
-
website: ""
|
|
6255
|
-
},
|
|
6256
|
-
description: "",
|
|
6257
|
-
extension: "",
|
|
6258
|
-
id: "",
|
|
6259
|
-
name: "",
|
|
6260
|
-
specifications: []
|
|
6261
|
-
};
|
|
6262
|
-
}
|
|
6263
|
-
function defaultLocalState() {
|
|
6264
|
-
return {};
|
|
6265
|
-
}
|
|
6266
|
-
function createGlobalState(state) {
|
|
6267
|
-
return {
|
|
6268
|
-
...defaultGlobalState(),
|
|
6269
|
-
...state || {}
|
|
6270
|
-
};
|
|
6271
|
-
}
|
|
6272
|
-
function createLocalState(state) {
|
|
6273
|
-
return {
|
|
6274
|
-
...defaultLocalState(),
|
|
6275
|
-
...state || {}
|
|
6276
|
-
};
|
|
6277
|
-
}
|
|
6278
|
-
function createState(baseState, globalState, localState) {
|
|
6279
|
-
return {
|
|
6280
|
-
...createBaseState(baseState?.auth, baseState?.document),
|
|
6281
|
-
global: createGlobalState(globalState),
|
|
6282
|
-
local: createLocalState(localState)
|
|
6283
|
-
};
|
|
6284
|
-
}
|
|
6285
6831
|
//#endregion
|
|
6286
6832
|
//#region ../document-model/dist/index.js
|
|
6287
6833
|
const isStateOfType$1 = (state) => {
|
|
@@ -7360,6 +7906,6 @@ const driveDocumentModelModule = {
|
|
|
7360
7906
|
}
|
|
7361
7907
|
};
|
|
7362
7908
|
//#endregion
|
|
7363
|
-
export {
|
|
7909
|
+
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 };
|
|
7364
7910
|
|
|
7365
|
-
//# sourceMappingURL=document-drive-
|
|
7911
|
+
//# sourceMappingURL=document-drive-QCAIGn3V.js.map
|