@powerhousedao/shared 6.2.2-dev.15 → 6.2.2-dev.16
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/clis/index.d.mts +9 -9
- package/dist/connect/config-loader.d.ts +1 -1
- package/dist/connect/index.d.ts +1 -1
- package/dist/document-drive/index.d.ts +2 -2
- package/dist/document-drive/index.d.ts.map +1 -1
- package/dist/document-model/index.d.ts +3 -3
- package/dist/document-model/index.js +616 -121
- package/dist/document-model/index.js.map +1 -1
- package/dist/document-model/utils.js +1 -1
- package/dist/{index-BKbRLfnp.d.ts → index-T2LTMq8r.d.ts} +205 -3
- package/dist/index-T2LTMq8r.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/processors/index.d.ts +1 -1
- package/dist/registry/index.d.ts +2 -2
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/manifest-slim.d.ts +1 -1
- package/dist/registry/manifest-slim.d.ts.map +1 -1
- package/dist/{types-Bd8i6VlX.d.ts → types-CKsl6Smi.d.ts} +92 -6
- package/dist/types-CKsl6Smi.d.ts.map +1 -0
- package/dist/{types-CBShShg8.d.ts → types-DN7Z4Qjw.d.ts} +2 -2
- package/dist/{types-CBShShg8.d.ts.map → types-DN7Z4Qjw.d.ts.map} +1 -1
- package/dist/{utils-DKOFCM0Q.js → utils-CTt1XRn-.js} +36 -2
- package/dist/utils-CTt1XRn-.js.map +1 -0
- package/package.json +1 -1
- package/dist/index-BKbRLfnp.d.ts.map +0 -1
- package/dist/types-Bd8i6VlX.d.ts.map +0 -1
- package/dist/utils-DKOFCM0Q.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as base64UrlToBytes, c as getUnixTimestamp, i as base58Decode, l as hashBrowser, n as generateId, o as buildOperationSignatureMessage, r as ab2hex, s as buildOperationSignatureParams, t as deriveOperationId, u as hex2ab } from "../utils-CTt1XRn-.js";
|
|
2
2
|
import { generateMock } from "./mock.js";
|
|
3
3
|
import { ZodError, z } from "zod";
|
|
4
4
|
import { stringify } from "safe-stable-stringify";
|
|
@@ -39,6 +39,75 @@ var DowngradeNotSupportedError = class extends Error {
|
|
|
39
39
|
this.toVersion = toVersion;
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when INITIALIZE_AUTH is applied to an already-initialized auth scope.
|
|
44
|
+
* The genesis action is valid only at auth revision zero.
|
|
45
|
+
*/
|
|
46
|
+
var AuthAlreadyInitializedError = class extends Error {
|
|
47
|
+
documentId;
|
|
48
|
+
constructor(documentId) {
|
|
49
|
+
super(`Auth scope already initialized for document ${documentId}: INITIALIZE_AUTH is valid only at auth revision zero`);
|
|
50
|
+
this.name = "AuthAlreadyInitializedError";
|
|
51
|
+
this.documentId = documentId;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Thrown when INITIALIZE_AUTH is not signed by the document creator (its signer
|
|
56
|
+
* does not match `header.sig.publicKey`), so it cannot set the auth policy.
|
|
57
|
+
*/
|
|
58
|
+
var AuthInitializerNotCreatorError = class extends Error {
|
|
59
|
+
documentId;
|
|
60
|
+
constructor(documentId) {
|
|
61
|
+
super(`INITIALIZE_AUTH for document ${documentId} must be signed by the document creator`);
|
|
62
|
+
this.name = "AuthInitializerNotCreatorError";
|
|
63
|
+
this.documentId = documentId;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Thrown when INITIALIZE_AUTH carries a version below 1. Version 0 is reserved
|
|
68
|
+
* for the uninitialized auth scope.
|
|
69
|
+
*/
|
|
70
|
+
var InvalidAuthVersionError = class extends Error {
|
|
71
|
+
documentId;
|
|
72
|
+
version;
|
|
73
|
+
constructor(documentId, version) {
|
|
74
|
+
super(`Invalid auth policy version ${version} for document ${documentId}: INITIALIZE_AUTH requires an integer version >= 1`);
|
|
75
|
+
this.name = "InvalidAuthVersionError";
|
|
76
|
+
this.documentId = documentId;
|
|
77
|
+
this.version = version;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/** Thrown when a duplicate would lose the source policy's version or creator binding. */
|
|
81
|
+
var AuthPolicyNotPreservedError = class extends Error {
|
|
82
|
+
documentId;
|
|
83
|
+
constructor(documentId) {
|
|
84
|
+
super(`Duplicating document ${documentId} would not preserve its auth policy: the copy loses the policy version or its creator binding`);
|
|
85
|
+
this.name = "AuthPolicyNotPreservedError";
|
|
86
|
+
this.documentId = documentId;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Thrown when a grant referenced by REMOVE_GRANT or MOVE_GRANT does not exist.
|
|
91
|
+
*/
|
|
92
|
+
var GrantNotFoundError = class extends Error {
|
|
93
|
+
grantId;
|
|
94
|
+
constructor(grantId) {
|
|
95
|
+
super(`Grant not found in auth scope: ${grantId}`);
|
|
96
|
+
this.name = "GrantNotFoundError";
|
|
97
|
+
this.grantId = grantId;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Thrown when a disallowed action (UNDO, REDO, PRUNE) targets the auth scope.
|
|
102
|
+
*/
|
|
103
|
+
var AuthActionNotAllowedError = class extends Error {
|
|
104
|
+
actionType;
|
|
105
|
+
constructor(actionType) {
|
|
106
|
+
super(`${actionType} is not permitted on the auth scope`);
|
|
107
|
+
this.name = "AuthActionNotAllowedError";
|
|
108
|
+
this.actionType = actionType;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
42
111
|
var HashMismatchError = class extends Error {
|
|
43
112
|
_scope;
|
|
44
113
|
_document;
|
|
@@ -934,6 +1003,231 @@ const actions = {
|
|
|
934
1003
|
...documentModelActions
|
|
935
1004
|
};
|
|
936
1005
|
//#endregion
|
|
1006
|
+
//#region document-model/document-type.ts
|
|
1007
|
+
const documentModelDocumentType = "powerhouse/document-model";
|
|
1008
|
+
const groupDocumentType = "@powerhousedao/document-group";
|
|
1009
|
+
//#endregion
|
|
1010
|
+
//#region document-model/auth-v1.ts
|
|
1011
|
+
/** Maximum number of grants in a policy. */
|
|
1012
|
+
const MAX_AUTH_GRANTS = 100;
|
|
1013
|
+
/** Maximum nesting depth of a condition tree. */
|
|
1014
|
+
const MAX_CONDITION_DEPTH = 10;
|
|
1015
|
+
/** Maximum node count (conditions plus operands) of a condition tree. */
|
|
1016
|
+
const MAX_CONDITION_NODES = 100;
|
|
1017
|
+
/** Maximum entries in an execute capability's operation list. */
|
|
1018
|
+
const MAX_CAPABILITY_OPERATIONS = 100;
|
|
1019
|
+
/**
|
|
1020
|
+
* Thrown when a grant violates the v1 validation rules. The message is stored
|
|
1021
|
+
* on error operations, so it must be a pure function of the input.
|
|
1022
|
+
*/
|
|
1023
|
+
var InvalidGrantError = class extends Error {
|
|
1024
|
+
grantId;
|
|
1025
|
+
constructor(grantId, problem) {
|
|
1026
|
+
super(`Invalid grant "${grantId}": ${problem}`);
|
|
1027
|
+
this.name = "InvalidGrantError";
|
|
1028
|
+
this.grantId = grantId;
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
/** Thrown for a `{ group }` principal on a group document: references never chain. */
|
|
1032
|
+
var GroupPrincipalNotAllowedError = class extends Error {
|
|
1033
|
+
grantId;
|
|
1034
|
+
constructor(grantId) {
|
|
1035
|
+
super(`Grant "${grantId}" uses a group principal on a group document: a group's auth scope cannot reference other groups`);
|
|
1036
|
+
this.name = "GroupPrincipalNotAllowedError";
|
|
1037
|
+
this.grantId = grantId;
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
const GRANT_KEYS = new Set([
|
|
1041
|
+
"id",
|
|
1042
|
+
"description",
|
|
1043
|
+
"effect",
|
|
1044
|
+
"principal",
|
|
1045
|
+
"capability",
|
|
1046
|
+
"where"
|
|
1047
|
+
]);
|
|
1048
|
+
const PRINCIPAL_KINDS = new Set([
|
|
1049
|
+
"anyone",
|
|
1050
|
+
"address",
|
|
1051
|
+
"group",
|
|
1052
|
+
"match"
|
|
1053
|
+
]);
|
|
1054
|
+
const COMPARISON_CONDITION_KINDS = new Set([
|
|
1055
|
+
"eq",
|
|
1056
|
+
"ne",
|
|
1057
|
+
"lt",
|
|
1058
|
+
"lte",
|
|
1059
|
+
"gt",
|
|
1060
|
+
"gte"
|
|
1061
|
+
]);
|
|
1062
|
+
function isPlainValue(value) {
|
|
1063
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1064
|
+
}
|
|
1065
|
+
function operandProblem(value, capabilityScope, budget) {
|
|
1066
|
+
budget.nodes -= 1;
|
|
1067
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
1068
|
+
if (!isPlainValue(value)) return "operand must be an object";
|
|
1069
|
+
const keys = Object.keys(value);
|
|
1070
|
+
if (keys.length !== 1) return "operand must have exactly one of attr or lit";
|
|
1071
|
+
if (keys[0] === "attr") {
|
|
1072
|
+
const attr = value.attr;
|
|
1073
|
+
if (typeof attr !== "string" || attr.length === 0) return "attr must be a non-empty string";
|
|
1074
|
+
if (capabilityScope !== void 0 && capabilityScope !== "*" && attr.startsWith("doc.")) {
|
|
1075
|
+
const pathScope = attr.split(".")[1] ?? "";
|
|
1076
|
+
if (pathScope !== capabilityScope) return `condition path "${attr}" reads scope "${pathScope}" but the capability covers only scope "${capabilityScope}"`;
|
|
1077
|
+
}
|
|
1078
|
+
return null;
|
|
1079
|
+
}
|
|
1080
|
+
if (keys[0] === "lit") {
|
|
1081
|
+
const lit = value.lit;
|
|
1082
|
+
if (lit !== null && typeof lit !== "string" && typeof lit !== "number" && typeof lit !== "boolean") return "lit must be a string, number, boolean, or null";
|
|
1083
|
+
if (typeof lit === "number" && !Number.isFinite(lit)) return "lit must be a finite number";
|
|
1084
|
+
if (typeof lit === "number" && Object.is(lit, -0)) return "lit must not be negative zero";
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1087
|
+
return `unknown operand kind "${keys[0]}"`;
|
|
1088
|
+
}
|
|
1089
|
+
function conditionProblem(value, capabilityScope, depth, budget) {
|
|
1090
|
+
if (depth > 10) return `condition exceeds depth 10`;
|
|
1091
|
+
budget.nodes -= 1;
|
|
1092
|
+
if (budget.nodes < 0) return `condition exceeds 100 nodes`;
|
|
1093
|
+
if (!isPlainValue(value)) return "condition must be an object";
|
|
1094
|
+
const keys = Object.keys(value);
|
|
1095
|
+
if (keys.length !== 1) return "condition must have exactly one operator";
|
|
1096
|
+
const kind = keys[0];
|
|
1097
|
+
const body = value[kind];
|
|
1098
|
+
if (COMPARISON_CONDITION_KINDS.has(kind)) {
|
|
1099
|
+
if (!Array.isArray(body) || body.length !== 2) return `${kind} requires a pair of operands`;
|
|
1100
|
+
for (const operand of body) {
|
|
1101
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
1102
|
+
if (problem !== null) return problem;
|
|
1103
|
+
}
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
if (kind === "in" || kind === "notIn") {
|
|
1107
|
+
if (!Array.isArray(body) || body.length !== 2 || !Array.isArray(body[1])) return `${kind} requires an operand and an operand list`;
|
|
1108
|
+
const first = operandProblem(body[0], capabilityScope, budget);
|
|
1109
|
+
if (first !== null) return first;
|
|
1110
|
+
for (const operand of body[1]) {
|
|
1111
|
+
const problem = operandProblem(operand, capabilityScope, budget);
|
|
1112
|
+
if (problem !== null) return problem;
|
|
1113
|
+
}
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
if (kind === "exists") return operandProblem(body, capabilityScope, budget);
|
|
1117
|
+
if (kind === "and" || kind === "or") {
|
|
1118
|
+
if (!Array.isArray(body)) return `${kind} requires a condition list`;
|
|
1119
|
+
for (const child of body) {
|
|
1120
|
+
const problem = conditionProblem(child, capabilityScope, depth + 1, budget);
|
|
1121
|
+
if (problem !== null) return problem;
|
|
1122
|
+
}
|
|
1123
|
+
return null;
|
|
1124
|
+
}
|
|
1125
|
+
if (kind === "not") return conditionProblem(body, capabilityScope, depth + 1, budget);
|
|
1126
|
+
return `unknown condition operator "${kind}"`;
|
|
1127
|
+
}
|
|
1128
|
+
function principalProblem(value, capabilityScope) {
|
|
1129
|
+
if (!isPlainValue(value)) return "principal must be an object";
|
|
1130
|
+
const keys = Object.keys(value);
|
|
1131
|
+
if (keys.length !== 1 || !PRINCIPAL_KINDS.has(keys[0])) return "principal must have exactly one of anyone, address, group, or match";
|
|
1132
|
+
const kind = keys[0];
|
|
1133
|
+
if (kind === "anyone" && value.anyone !== true) return "anyone must be true";
|
|
1134
|
+
if (kind === "address") {
|
|
1135
|
+
const address = value.address;
|
|
1136
|
+
if (typeof address !== "string" || address.length === 0) return "address must be a non-empty string";
|
|
1137
|
+
}
|
|
1138
|
+
if (kind === "group") {
|
|
1139
|
+
const group = value.group;
|
|
1140
|
+
if (typeof group !== "string" || group.length === 0) return "group must be a non-empty string";
|
|
1141
|
+
}
|
|
1142
|
+
if (kind === "match") return conditionProblem(value.match, capabilityScope, 1, { nodes: 100 });
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
function capabilityProblem(value) {
|
|
1146
|
+
if (!isPlainValue(value)) return "capability must be an object";
|
|
1147
|
+
const can = value.can;
|
|
1148
|
+
if (can !== "read" && can !== "execute") return "capability.can must be read or execute";
|
|
1149
|
+
const allowedKeys = can === "execute" ? [
|
|
1150
|
+
"can",
|
|
1151
|
+
"scope",
|
|
1152
|
+
"operation"
|
|
1153
|
+
] : ["can", "scope"];
|
|
1154
|
+
const unknownKeys = Object.keys(value).filter((key) => !allowedKeys.includes(key)).sort();
|
|
1155
|
+
if (unknownKeys.length > 0) return `unknown capability key "${unknownKeys[0]}"`;
|
|
1156
|
+
if (value.scope !== void 0) {
|
|
1157
|
+
if (typeof value.scope !== "string" || value.scope.length === 0) return "capability.scope must be a non-empty string";
|
|
1158
|
+
}
|
|
1159
|
+
if (can === "execute" && value.operation !== void 0) {
|
|
1160
|
+
const operation = value.operation;
|
|
1161
|
+
if (!Array.isArray(operation)) return "capability.operation must be an array";
|
|
1162
|
+
if (operation.length > 100) return `capability.operation exceeds 100 entries`;
|
|
1163
|
+
for (const entry of operation) if (typeof entry !== "string" || entry.length === 0) return "capability.operation entries must be non-empty strings";
|
|
1164
|
+
}
|
|
1165
|
+
return null;
|
|
1166
|
+
}
|
|
1167
|
+
/** Returns the first v1-rule violation, or null. Pure, total, deterministic. */
|
|
1168
|
+
function grantProblem(value) {
|
|
1169
|
+
if (!isPlainValue(value)) return "grant must be an object";
|
|
1170
|
+
const unknownKeys = Object.keys(value).filter((key) => !GRANT_KEYS.has(key)).sort();
|
|
1171
|
+
if (unknownKeys.length > 0) return `unknown grant key "${unknownKeys[0]}"`;
|
|
1172
|
+
if (typeof value.id !== "string" || value.id.length === 0) return "id must be a non-empty string";
|
|
1173
|
+
if (typeof value.description !== "string") return "description must be a string";
|
|
1174
|
+
if (value.effect !== "allow" && value.effect !== "deny") return "effect must be allow or deny";
|
|
1175
|
+
const capabilityValue = value.capability;
|
|
1176
|
+
const capability = capabilityProblem(capabilityValue);
|
|
1177
|
+
if (capability !== null) return capability;
|
|
1178
|
+
const capabilityScope = capabilityValue.scope;
|
|
1179
|
+
const principal = principalProblem(value.principal, capabilityScope);
|
|
1180
|
+
if (principal !== null) return principal;
|
|
1181
|
+
if (value.where !== void 0) return conditionProblem(value.where, capabilityScope, 1, { nodes: 100 });
|
|
1182
|
+
return null;
|
|
1183
|
+
}
|
|
1184
|
+
const GrantSchema = () => z.custom((value) => grantProblem(value) === null);
|
|
1185
|
+
/** V1 shape rules plus the group-document group-principal ban. */
|
|
1186
|
+
function assertValidGrant(grant, documentType) {
|
|
1187
|
+
const grantId = isPlainValue(grant) && typeof grant.id === "string" ? grant.id : "";
|
|
1188
|
+
const problem = grantProblem(grant);
|
|
1189
|
+
if (problem !== null) throw new InvalidGrantError(grantId, problem);
|
|
1190
|
+
if (documentType === "@powerhousedao/document-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
|
|
1191
|
+
}
|
|
1192
|
+
/** Validates an initial grant list: the count cap plus every grant. */
|
|
1193
|
+
function assertValidInitialGrants(grants, documentType) {
|
|
1194
|
+
if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
|
|
1195
|
+
for (const grant of grants) assertValidGrant(grant, documentType);
|
|
1196
|
+
}
|
|
1197
|
+
/** Validates a grant upsert: the grant itself plus the count cap on append. */
|
|
1198
|
+
function assertValidGrantUpsert(grant, existing, documentType) {
|
|
1199
|
+
assertValidGrant(grant, documentType);
|
|
1200
|
+
if (!existing.some((g) => g.id === grant.id) && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
|
|
1201
|
+
}
|
|
1202
|
+
function capabilityCovers(capability, request) {
|
|
1203
|
+
if (capability.can !== request.verb) return false;
|
|
1204
|
+
const scope = capability.scope;
|
|
1205
|
+
if (scope !== void 0 && scope !== "*" && scope !== request.scope) return false;
|
|
1206
|
+
if (capability.can === "execute") {
|
|
1207
|
+
if (capability.operation === void 0) return true;
|
|
1208
|
+
return request.operation !== void 0 && capability.operation.includes(request.operation);
|
|
1209
|
+
}
|
|
1210
|
+
return true;
|
|
1211
|
+
}
|
|
1212
|
+
function principalMatches(principal, subject) {
|
|
1213
|
+
if ("anyone" in principal) return true;
|
|
1214
|
+
if ("address" in principal) return subject.address !== void 0 && subject.address.toLowerCase() === principal.address.toLowerCase();
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Evaluates a v1 grant stack: default deny, last applicable grant wins.
|
|
1219
|
+
* Group and match principals and `where` conditions are not evaluated yet; a
|
|
1220
|
+
* grant that uses any of them never applies.
|
|
1221
|
+
*/
|
|
1222
|
+
function evaluateGrants(grants, subject, request) {
|
|
1223
|
+
let decision = "deny";
|
|
1224
|
+
for (const grant of grants) {
|
|
1225
|
+
if (grant.where !== void 0) continue;
|
|
1226
|
+
if (capabilityCovers(grant.capability, request) && principalMatches(grant.principal, subject)) decision = grant.effect;
|
|
1227
|
+
}
|
|
1228
|
+
return decision;
|
|
1229
|
+
}
|
|
1230
|
+
//#endregion
|
|
937
1231
|
//#region document-model/constants.ts
|
|
938
1232
|
const documentModelFileExtension = "phdm";
|
|
939
1233
|
const documentModelInitialLocalState = {};
|
|
@@ -1520,8 +1814,300 @@ const HASH_ALGORITHM_SHA512 = "sha512";
|
|
|
1520
1814
|
const HASH_ENCODING_BASE64 = "base64";
|
|
1521
1815
|
const HASH_ENCODING_HEX = "hex";
|
|
1522
1816
|
//#endregion
|
|
1523
|
-
//#region document-model/
|
|
1524
|
-
|
|
1817
|
+
//#region document-model/state.ts
|
|
1818
|
+
/**
|
|
1819
|
+
* Creates a default PHAuthState
|
|
1820
|
+
*/
|
|
1821
|
+
function defaultAuthState() {
|
|
1822
|
+
return {
|
|
1823
|
+
version: 0,
|
|
1824
|
+
grants: []
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
/**
|
|
1828
|
+
* Creates a default PHDocumentState
|
|
1829
|
+
*/
|
|
1830
|
+
function defaultDocumentState() {
|
|
1831
|
+
return {
|
|
1832
|
+
version: 0,
|
|
1833
|
+
hash: {
|
|
1834
|
+
algorithm: HASH_ALGORITHM_SHA1,
|
|
1835
|
+
encoding: HASH_ENCODING_BASE64
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1839
|
+
/**
|
|
1840
|
+
* Creates a default PHBaseState with auth and document properties
|
|
1841
|
+
*/
|
|
1842
|
+
function defaultBaseState() {
|
|
1843
|
+
return {
|
|
1844
|
+
auth: defaultAuthState(),
|
|
1845
|
+
document: defaultDocumentState()
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
/**
|
|
1849
|
+
* Creates a PHAuthState with the given properties
|
|
1850
|
+
*/
|
|
1851
|
+
function createAuthState(auth) {
|
|
1852
|
+
return {
|
|
1853
|
+
...defaultAuthState(),
|
|
1854
|
+
...auth
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
/**
|
|
1858
|
+
* Creates a PHDocumentState with the given properties
|
|
1859
|
+
*/
|
|
1860
|
+
function createDocumentState(document) {
|
|
1861
|
+
return {
|
|
1862
|
+
...defaultDocumentState(),
|
|
1863
|
+
...document
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Creates a PHBaseState with the given auth and document properties
|
|
1868
|
+
*/
|
|
1869
|
+
function createBaseState(auth, document) {
|
|
1870
|
+
return {
|
|
1871
|
+
auth: createAuthState(auth),
|
|
1872
|
+
document: createDocumentState(document)
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Backfills the auth scope to the default for legacy documents serialized with
|
|
1877
|
+
* an empty `auth`. Replaces only `state.auth`. Idempotent.
|
|
1878
|
+
*/
|
|
1879
|
+
function backfillAuthState(state) {
|
|
1880
|
+
return {
|
|
1881
|
+
...state,
|
|
1882
|
+
auth: createAuthState(state.auth)
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
function defaultGlobalState() {
|
|
1886
|
+
return {
|
|
1887
|
+
...defaultBaseState(),
|
|
1888
|
+
author: {
|
|
1889
|
+
name: "",
|
|
1890
|
+
website: ""
|
|
1891
|
+
},
|
|
1892
|
+
description: "",
|
|
1893
|
+
extension: "",
|
|
1894
|
+
id: "",
|
|
1895
|
+
name: "",
|
|
1896
|
+
specifications: []
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
function defaultLocalState() {
|
|
1900
|
+
return {};
|
|
1901
|
+
}
|
|
1902
|
+
function defaultPHState() {
|
|
1903
|
+
return {
|
|
1904
|
+
...defaultBaseState(),
|
|
1905
|
+
global: defaultGlobalState(),
|
|
1906
|
+
local: defaultLocalState()
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
function createGlobalState(state) {
|
|
1910
|
+
return {
|
|
1911
|
+
...defaultGlobalState(),
|
|
1912
|
+
...state || {}
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
function createLocalState(state) {
|
|
1916
|
+
return {
|
|
1917
|
+
...defaultLocalState(),
|
|
1918
|
+
...state || {}
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
function createState(baseState, globalState, localState) {
|
|
1922
|
+
return {
|
|
1923
|
+
...createBaseState(baseState?.auth, baseState?.document),
|
|
1924
|
+
global: createGlobalState(globalState),
|
|
1925
|
+
local: createLocalState(localState)
|
|
1926
|
+
};
|
|
1927
|
+
}
|
|
1928
|
+
//#endregion
|
|
1929
|
+
//#region document-model/auth.ts
|
|
1930
|
+
const AUTH_ACTION_TYPES = [
|
|
1931
|
+
"INITIALIZE_AUTH",
|
|
1932
|
+
"SET_GRANT",
|
|
1933
|
+
"REMOVE_GRANT",
|
|
1934
|
+
"MOVE_GRANT"
|
|
1935
|
+
];
|
|
1936
|
+
function isAuthAction(action) {
|
|
1937
|
+
return AUTH_ACTION_TYPES.includes(action.type);
|
|
1938
|
+
}
|
|
1939
|
+
/** Highest known policy version; decide() fails closed above it. */
|
|
1940
|
+
const MAX_SUPPORTED_AUTH_VERSION = 1;
|
|
1941
|
+
const InitializeAuthActionInputSchema = () => z.object({
|
|
1942
|
+
version: z.number().int().min(1),
|
|
1943
|
+
grants: z.array(GrantSchema()).max(100)
|
|
1944
|
+
});
|
|
1945
|
+
const SetGrantActionInputSchema = () => z.object({ grant: GrantSchema() });
|
|
1946
|
+
const RemoveGrantActionInputSchema = () => z.object({ id: z.string() });
|
|
1947
|
+
const MoveGrantActionInputSchema = () => z.object({
|
|
1948
|
+
id: z.string(),
|
|
1949
|
+
index: z.number()
|
|
1950
|
+
});
|
|
1951
|
+
const initializeAuth = (input) => createAction("INITIALIZE_AUTH", input, void 0, InitializeAuthActionInputSchema, "auth");
|
|
1952
|
+
const setGrant = (input) => createAction("SET_GRANT", input, void 0, SetGrantActionInputSchema, "auth");
|
|
1953
|
+
const removeGrant = (input) => createAction("REMOVE_GRANT", input, void 0, RemoveGrantActionInputSchema, "auth");
|
|
1954
|
+
const moveGrant = (input) => createAction("MOVE_GRANT", input, void 0, MoveGrantActionInputSchema, "auth");
|
|
1955
|
+
/**
|
|
1956
|
+
* Destructuring a null input (reachable via raw synced operations) would
|
|
1957
|
+
* store an engine-specific TypeError message on the error operation.
|
|
1958
|
+
*/
|
|
1959
|
+
function assertActionInputShape(input) {
|
|
1960
|
+
if (!isPlainValue(input)) throw new InvalidActionInputError({ input: "must be an object" });
|
|
1961
|
+
}
|
|
1962
|
+
function withGrants(document, grants) {
|
|
1963
|
+
return {
|
|
1964
|
+
...document,
|
|
1965
|
+
state: {
|
|
1966
|
+
...document.state,
|
|
1967
|
+
auth: {
|
|
1968
|
+
...document.state.auth,
|
|
1969
|
+
grants
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
const P256_PUBKEY_MULTICODEC = [128, 36];
|
|
1975
|
+
const DID_KEY_PREFIX = "did:key:z";
|
|
1976
|
+
function bytesEqual(a, b) {
|
|
1977
|
+
if (a.length !== b.length) return false;
|
|
1978
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
1979
|
+
return true;
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* True when `signerKey` (an ActionSigner app key, a did:key) identifies the same
|
|
1983
|
+
* key recorded as the document creator. Returns false
|
|
1984
|
+
* when there is no creator (empty JWK) or no signer key.
|
|
1985
|
+
*/
|
|
1986
|
+
function isDocumentCreator(creatorKey, signerKey) {
|
|
1987
|
+
if (!creatorKey?.x || !creatorKey.y) return false;
|
|
1988
|
+
if (!signerKey || !signerKey.startsWith(DID_KEY_PREFIX)) return false;
|
|
1989
|
+
const decoded = base58Decode(signerKey.slice(9));
|
|
1990
|
+
if (!decoded || decoded.length !== 35) return false;
|
|
1991
|
+
if (decoded[0] !== P256_PUBKEY_MULTICODEC[0] || decoded[1] !== P256_PUBKEY_MULTICODEC[1]) return false;
|
|
1992
|
+
const parityPrefix = decoded[2];
|
|
1993
|
+
if (parityPrefix !== 2 && parityPrefix !== 3) return false;
|
|
1994
|
+
const didX = decoded.subarray(3, 35);
|
|
1995
|
+
const jwkX = base64UrlToBytes(creatorKey.x);
|
|
1996
|
+
const jwkY = base64UrlToBytes(creatorKey.y);
|
|
1997
|
+
if (jwkX.length !== 32 || jwkY.length !== 32) return false;
|
|
1998
|
+
if (!bytesEqual(didX, jwkX)) return false;
|
|
1999
|
+
return (jwkY[31] & 1) === 1 === (parityPrefix === 3);
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* Sets the initial policy. Valid only while the auth scope is uninitialized
|
|
2003
|
+
* (version 0). The input version is the policy language version and must be an
|
|
2004
|
+
* integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
|
|
2005
|
+
* document it must be signed by the document creator (`header.sig.publicKey`).
|
|
2006
|
+
*/
|
|
2007
|
+
function applyInitializeAuthAction(document, action) {
|
|
2008
|
+
assertActionInputShape(action.input);
|
|
2009
|
+
const { version, grants } = action.input;
|
|
2010
|
+
if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
|
|
2011
|
+
if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
|
|
2012
|
+
if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
2013
|
+
assertValidInitialGrants(grants, document.header.documentType);
|
|
2014
|
+
const creatorKey = document.header.sig.publicKey;
|
|
2015
|
+
const signerKey = action.context?.signer?.app.key;
|
|
2016
|
+
const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
|
|
2017
|
+
if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
|
|
2018
|
+
const creator = hasCreator ? signerKey : void 0;
|
|
2019
|
+
return {
|
|
2020
|
+
...document,
|
|
2021
|
+
state: {
|
|
2022
|
+
...document.state,
|
|
2023
|
+
auth: createAuthState(creator ? {
|
|
2024
|
+
version,
|
|
2025
|
+
grants,
|
|
2026
|
+
creator
|
|
2027
|
+
} : {
|
|
2028
|
+
version,
|
|
2029
|
+
grants
|
|
2030
|
+
})
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
/** Upserts a grant by id: replaces in place if present, otherwise appends. */
|
|
2035
|
+
function applySetGrantAction(document, action) {
|
|
2036
|
+
assertActionInputShape(action.input);
|
|
2037
|
+
const { grant } = action.input;
|
|
2038
|
+
const grants = document.state.auth.grants;
|
|
2039
|
+
assertValidGrantUpsert(grant, grants, document.header.documentType);
|
|
2040
|
+
return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
|
|
2041
|
+
}
|
|
2042
|
+
/** Removes a grant by id; throws if the id is not present. */
|
|
2043
|
+
function applyRemoveGrantAction(document, action) {
|
|
2044
|
+
assertActionInputShape(action.input);
|
|
2045
|
+
const { id } = action.input;
|
|
2046
|
+
const grants = document.state.auth.grants;
|
|
2047
|
+
if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
|
|
2048
|
+
return withGrants(document, grants.filter((g) => g.id !== id));
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* Moves a grant by id to a new index. Order is load-bearing (the last
|
|
2052
|
+
* applicable grant wins), so the relative order of the other grants is kept.
|
|
2053
|
+
* The target index is clamped to the valid range; an unknown id throws.
|
|
2054
|
+
*/
|
|
2055
|
+
function applyMoveGrantAction(document, action) {
|
|
2056
|
+
assertActionInputShape(action.input);
|
|
2057
|
+
const { id, index } = action.input;
|
|
2058
|
+
const grants = document.state.auth.grants;
|
|
2059
|
+
const from = grants.findIndex((g) => g.id === id);
|
|
2060
|
+
if (from === -1) throw new GrantNotFoundError(id);
|
|
2061
|
+
const next = [...grants];
|
|
2062
|
+
const [moved] = next.splice(from, 1);
|
|
2063
|
+
const to = Math.max(0, Math.min(index, next.length));
|
|
2064
|
+
next.splice(to, 0, moved);
|
|
2065
|
+
return withGrants(document, next);
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Dispatches an auth-scope action to its handler. This is the auth scope's
|
|
2069
|
+
* dedicated reducer: it is applied by the base reducer instead of the model
|
|
2070
|
+
* reducer, mirroring the document-scope platform handlers. Unknown types are a
|
|
2071
|
+
* no-op, matching the model-reducer default.
|
|
2072
|
+
*/
|
|
2073
|
+
function applyAuthAction(document, action) {
|
|
2074
|
+
switch (action.type) {
|
|
2075
|
+
case "INITIALIZE_AUTH": return applyInitializeAuthAction(document, action);
|
|
2076
|
+
case "SET_GRANT": return applySetGrantAction(document, action);
|
|
2077
|
+
case "REMOVE_GRANT": return applyRemoveGrantAction(document, action);
|
|
2078
|
+
case "MOVE_GRANT": return applyMoveGrantAction(document, action);
|
|
2079
|
+
default: return document;
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
/**
|
|
2083
|
+
* Because only creators can initialize auth scopes, we must verify that either
|
|
2084
|
+
* the document has no auth or the version and creator match.
|
|
2085
|
+
*/
|
|
2086
|
+
function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
|
|
2087
|
+
if (!source || source.version === 0) return;
|
|
2088
|
+
if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
|
|
2089
|
+
}
|
|
2090
|
+
/** UNDO, REDO and PRUNE are rejected on the auth scope. */
|
|
2091
|
+
function assertAuthScopeActionAllowed(action) {
|
|
2092
|
+
if (action.scope === "auth" && [
|
|
2093
|
+
"UNDO",
|
|
2094
|
+
"REDO",
|
|
2095
|
+
"PRUNE"
|
|
2096
|
+
].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* Evaluates the auth policy for a single request. Pure and deterministic.
|
|
2100
|
+
*
|
|
2101
|
+
* An uninitialized policy (version 0, absent auth state, or a legacy `{}`
|
|
2102
|
+
* auth scope serialized before PHAuthState had a version) leaves the document
|
|
2103
|
+
* open. Once a policy exists the default is deny, and grants stack in order.
|
|
2104
|
+
*/
|
|
2105
|
+
function decide(auth, subject, request) {
|
|
2106
|
+
if (!auth || !auth.version) return "allow";
|
|
2107
|
+
if (request.verb === "execute" && request.scope === "auth" && subject.key !== void 0 && subject.key === auth.creator) return "allow";
|
|
2108
|
+
if (auth.version > 1) return "deny";
|
|
2109
|
+
return evaluateGrants(auth.grants, subject, request);
|
|
2110
|
+
}
|
|
1525
2111
|
//#endregion
|
|
1526
2112
|
//#region document-model/document-schema.ts
|
|
1527
2113
|
const BaseDocumentHeaderSchema = z.object({
|
|
@@ -1910,7 +2496,8 @@ const defaultCreateState = (state) => {
|
|
|
1910
2496
|
};
|
|
1911
2497
|
function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
|
|
1912
2498
|
const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
|
|
1913
|
-
|
|
2499
|
+
const backfilledInitialState = backfillAuthState(initialState);
|
|
2500
|
+
let documentState = backfilledInitialState;
|
|
1914
2501
|
const operationsToReplay = [];
|
|
1915
2502
|
const allScopes = new Set([
|
|
1916
2503
|
...Object.keys(operations),
|
|
@@ -1945,7 +2532,7 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
|
|
|
1945
2532
|
const document = {
|
|
1946
2533
|
header,
|
|
1947
2534
|
state: defaultCreateState(documentState),
|
|
1948
|
-
initialState,
|
|
2535
|
+
initialState: backfilledInitialState,
|
|
1949
2536
|
operations: initialOperations,
|
|
1950
2537
|
clipboard: []
|
|
1951
2538
|
};
|
|
@@ -2480,7 +3067,7 @@ function loadStateOperation(document, action) {
|
|
|
2480
3067
|
...document.header,
|
|
2481
3068
|
name: action.state.name
|
|
2482
3069
|
},
|
|
2483
|
-
state: action.state.data
|
|
3070
|
+
state: backfillAuthState(action.state.data)
|
|
2484
3071
|
};
|
|
2485
3072
|
}
|
|
2486
3073
|
//#endregion
|
|
@@ -2656,6 +3243,7 @@ function processUndoOperation(document, scope, customReducer, reuseOperationResu
|
|
|
2656
3243
|
function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
2657
3244
|
const { skip, ignoreSkipOperations = false, reuseOperationResultingState = false, operationResultingStateParser, pruneOnSkip = true, branch = "main" } = options;
|
|
2658
3245
|
let _action = actionFromAction(action);
|
|
3246
|
+
assertAuthScopeActionAllowed(_action);
|
|
2659
3247
|
let skipValue = skip ?? options.replayOptions?.operation.skip ?? 0;
|
|
2660
3248
|
let newDocument = { ...document };
|
|
2661
3249
|
let reuseLastOperationIndex = false;
|
|
@@ -2703,6 +3291,13 @@ function baseReducer(document, action, customReducer, dispatch, options = {}) {
|
|
|
2703
3291
|
}
|
|
2704
3292
|
newDocument = create(newDocument, (draft) => {
|
|
2705
3293
|
try {
|
|
3294
|
+
if (_action.scope === "auth") {
|
|
3295
|
+
const authState = applyAuthAction(newDocument, _action).state;
|
|
3296
|
+
unsafe(() => {
|
|
3297
|
+
draft.state = castDraft(authState);
|
|
3298
|
+
});
|
|
3299
|
+
return;
|
|
3300
|
+
}
|
|
2706
3301
|
const newState = customReducer(draft.state, _action, dispatch);
|
|
2707
3302
|
if (newState) unsafe(() => {
|
|
2708
3303
|
draft.state = castDraft(newState);
|
|
@@ -3502,10 +4097,10 @@ function applyInitialState(document, action) {
|
|
|
3502
4097
|
const input = action.input;
|
|
3503
4098
|
const newState = input.initialState || input.state;
|
|
3504
4099
|
if (newState) {
|
|
3505
|
-
document.state = {
|
|
4100
|
+
document.state = backfillAuthState({
|
|
3506
4101
|
...document.state,
|
|
3507
4102
|
...newState
|
|
3508
|
-
};
|
|
4103
|
+
});
|
|
3509
4104
|
document.initialState = document.state;
|
|
3510
4105
|
}
|
|
3511
4106
|
}
|
|
@@ -3567,7 +4162,6 @@ function computeUpgradeTransitions(manifest, fromVersion, toVersion) {
|
|
|
3567
4162
|
}
|
|
3568
4163
|
//#endregion
|
|
3569
4164
|
//#region document-model/versioned-replay.ts
|
|
3570
|
-
const NON_DOMAIN_SCOPES$1 = new Set(["auth", "document"]);
|
|
3571
4165
|
function highestReducerVersion(reducers) {
|
|
3572
4166
|
const keys = Object.keys(reducers).map(Number);
|
|
3573
4167
|
if (keys.length === 0) throw new Error("VersionedReplayConfig.reducers must not be empty");
|
|
@@ -3599,11 +4193,11 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3599
4193
|
const spine = (operations["document"] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
3600
4194
|
const upgrades = spine.filter((op) => op.action.type === "UPGRADE_DOCUMENT");
|
|
3601
4195
|
const legacyFallback = () => {
|
|
3602
|
-
const
|
|
4196
|
+
const replayOps = Object.fromEntries(Object.entries(operations).filter(([s]) => s !== "document"));
|
|
3603
4197
|
const latestVersion = highestReducerVersion(config.reducers);
|
|
3604
4198
|
const reducer = config.reducers[latestVersion];
|
|
3605
4199
|
return {
|
|
3606
|
-
...replayDocument(initialState,
|
|
4200
|
+
...replayDocument(initialState, replayOps, reducer, header, dispatch, {}, options),
|
|
3607
4201
|
operations
|
|
3608
4202
|
};
|
|
3609
4203
|
};
|
|
@@ -3627,14 +4221,14 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3627
4221
|
const a = op.action;
|
|
3628
4222
|
return a.input.fromVersion > 0 && a.input.fromVersion < a.input.toVersion;
|
|
3629
4223
|
});
|
|
3630
|
-
const
|
|
4224
|
+
const replayScopes = Object.keys(operations).filter((s) => s !== "document");
|
|
3631
4225
|
const scopeOps = {};
|
|
3632
|
-
for (const s of
|
|
4226
|
+
for (const s of replayScopes) scopeOps[s] = (operations[s] ?? []).slice().sort((a, b) => a.index - b.index);
|
|
3633
4227
|
const boundaries = validatedUpgrades.map((upgradeOp) => {
|
|
3634
4228
|
const revisionSnapshot = upgradeOp.action.input.revision;
|
|
3635
4229
|
const upgradeTimestamp = upgradeOp.timestampUtcMs;
|
|
3636
4230
|
const boundary = {};
|
|
3637
|
-
for (const s of
|
|
4231
|
+
for (const s of replayScopes) {
|
|
3638
4232
|
const ops = scopeOps[s] ?? [];
|
|
3639
4233
|
if (revisionSnapshot !== void 0) {
|
|
3640
4234
|
const rev = revisionSnapshot[s] ?? 0;
|
|
@@ -3652,7 +4246,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3652
4246
|
}
|
|
3653
4247
|
return boundary;
|
|
3654
4248
|
});
|
|
3655
|
-
for (let i = 1; i < boundaries.length; i++) for (const s of
|
|
4249
|
+
for (let i = 1; i < boundaries.length; i++) for (const s of replayScopes) {
|
|
3656
4250
|
const prev = boundaries[i - 1]?.[s] ?? 0;
|
|
3657
4251
|
const curr = boundaries[i]?.[s] ?? 0;
|
|
3658
4252
|
if (boundaries[i]) boundaries[i][s] = Math.max(prev, curr);
|
|
@@ -3664,10 +4258,11 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3664
4258
|
]);
|
|
3665
4259
|
const initialOperations = {};
|
|
3666
4260
|
for (const s of allScopes) initialOperations[s] = [];
|
|
4261
|
+
const backfilledSeed = backfillAuthState(seedState);
|
|
3667
4262
|
let document = {
|
|
3668
4263
|
header,
|
|
3669
|
-
state:
|
|
3670
|
-
initialState:
|
|
4264
|
+
state: backfilledSeed,
|
|
4265
|
+
initialState: backfilledSeed,
|
|
3671
4266
|
operations: initialOperations,
|
|
3672
4267
|
clipboard: []
|
|
3673
4268
|
};
|
|
@@ -3679,7 +4274,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3679
4274
|
const available = Object.keys(config.reducers).join(", ");
|
|
3680
4275
|
throw new Error(`No reducer registered for document version ${currentVersion}. Available versions: ${available}`);
|
|
3681
4276
|
}
|
|
3682
|
-
for (const s of
|
|
4277
|
+
for (const s of replayScopes) {
|
|
3683
4278
|
const ops = scopeOps[s] ?? [];
|
|
3684
4279
|
const segStart = k === 0 ? 0 : boundaries[k - 1]?.[s] ?? 0;
|
|
3685
4280
|
const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
|
|
@@ -3732,7 +4327,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3732
4327
|
}
|
|
3733
4328
|
};
|
|
3734
4329
|
if (!checkHashes) {
|
|
3735
|
-
const allReplayedOps =
|
|
4330
|
+
const allReplayedOps = replayScopes.flatMap((s) => scopeOps[s] ?? []);
|
|
3736
4331
|
for (const scope of Object.keys(document.state)) {
|
|
3737
4332
|
const capturedHash = segmentEndHashPerScope.get(scope);
|
|
3738
4333
|
const scopeHash = capturedHash !== void 0 ? capturedHash : hashDocumentStateForScope(document, scope);
|
|
@@ -3776,7 +4371,6 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
3776
4371
|
}
|
|
3777
4372
|
//#endregion
|
|
3778
4373
|
//#region document-model/files.ts
|
|
3779
|
-
const NON_DOMAIN_SCOPES = new Set(["auth", "document"]);
|
|
3780
4374
|
function zipAsync(data) {
|
|
3781
4375
|
return new Promise((resolve, reject) => {
|
|
3782
4376
|
zip(data, (err, out) => err ? reject(err) : resolve(out));
|
|
@@ -3883,7 +4477,7 @@ async function parseZipData(data) {
|
|
|
3883
4477
|
async function loadFromZipData(data, reducer, options) {
|
|
3884
4478
|
const { initialState, header, clearedOperations } = await parseZipData(data);
|
|
3885
4479
|
return {
|
|
3886
|
-
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) =>
|
|
4480
|
+
...replayDocument(initialState, Object.fromEntries(Object.entries(clearedOperations).filter(([scope]) => scope !== "document")), reducer, header, void 0, {}, options),
|
|
3887
4481
|
operations: clearedOperations
|
|
3888
4482
|
};
|
|
3889
4483
|
}
|
|
@@ -3919,105 +4513,6 @@ const getFileBrowser = (file) => {
|
|
|
3919
4513
|
return Promise.resolve().then(() => readFileBrowser(file));
|
|
3920
4514
|
};
|
|
3921
4515
|
//#endregion
|
|
3922
|
-
|
|
3923
|
-
/**
|
|
3924
|
-
* Creates a default PHAuthState
|
|
3925
|
-
*/
|
|
3926
|
-
function defaultAuthState() {
|
|
3927
|
-
return {};
|
|
3928
|
-
}
|
|
3929
|
-
/**
|
|
3930
|
-
* Creates a default PHDocumentState
|
|
3931
|
-
*/
|
|
3932
|
-
function defaultDocumentState() {
|
|
3933
|
-
return {
|
|
3934
|
-
version: 0,
|
|
3935
|
-
hash: {
|
|
3936
|
-
algorithm: HASH_ALGORITHM_SHA1,
|
|
3937
|
-
encoding: HASH_ENCODING_BASE64
|
|
3938
|
-
}
|
|
3939
|
-
};
|
|
3940
|
-
}
|
|
3941
|
-
/**
|
|
3942
|
-
* Creates a default PHBaseState with auth and document properties
|
|
3943
|
-
*/
|
|
3944
|
-
function defaultBaseState() {
|
|
3945
|
-
return {
|
|
3946
|
-
auth: defaultAuthState(),
|
|
3947
|
-
document: defaultDocumentState()
|
|
3948
|
-
};
|
|
3949
|
-
}
|
|
3950
|
-
/**
|
|
3951
|
-
* Creates a PHAuthState with the given properties
|
|
3952
|
-
*/
|
|
3953
|
-
function createAuthState(auth) {
|
|
3954
|
-
return {
|
|
3955
|
-
...defaultAuthState(),
|
|
3956
|
-
...auth
|
|
3957
|
-
};
|
|
3958
|
-
}
|
|
3959
|
-
/**
|
|
3960
|
-
* Creates a PHDocumentState with the given properties
|
|
3961
|
-
*/
|
|
3962
|
-
function createDocumentState(document) {
|
|
3963
|
-
return {
|
|
3964
|
-
...defaultDocumentState(),
|
|
3965
|
-
...document
|
|
3966
|
-
};
|
|
3967
|
-
}
|
|
3968
|
-
/**
|
|
3969
|
-
* Creates a PHBaseState with the given auth and document properties
|
|
3970
|
-
*/
|
|
3971
|
-
function createBaseState(auth, document) {
|
|
3972
|
-
return {
|
|
3973
|
-
auth: createAuthState(auth),
|
|
3974
|
-
document: createDocumentState(document)
|
|
3975
|
-
};
|
|
3976
|
-
}
|
|
3977
|
-
function defaultGlobalState() {
|
|
3978
|
-
return {
|
|
3979
|
-
...defaultBaseState(),
|
|
3980
|
-
author: {
|
|
3981
|
-
name: "",
|
|
3982
|
-
website: ""
|
|
3983
|
-
},
|
|
3984
|
-
description: "",
|
|
3985
|
-
extension: "",
|
|
3986
|
-
id: "",
|
|
3987
|
-
name: "",
|
|
3988
|
-
specifications: []
|
|
3989
|
-
};
|
|
3990
|
-
}
|
|
3991
|
-
function defaultLocalState() {
|
|
3992
|
-
return {};
|
|
3993
|
-
}
|
|
3994
|
-
function defaultPHState() {
|
|
3995
|
-
return {
|
|
3996
|
-
...defaultBaseState(),
|
|
3997
|
-
global: defaultGlobalState(),
|
|
3998
|
-
local: defaultLocalState()
|
|
3999
|
-
};
|
|
4000
|
-
}
|
|
4001
|
-
function createGlobalState(state) {
|
|
4002
|
-
return {
|
|
4003
|
-
...defaultGlobalState(),
|
|
4004
|
-
...state || {}
|
|
4005
|
-
};
|
|
4006
|
-
}
|
|
4007
|
-
function createLocalState(state) {
|
|
4008
|
-
return {
|
|
4009
|
-
...defaultLocalState(),
|
|
4010
|
-
...state || {}
|
|
4011
|
-
};
|
|
4012
|
-
}
|
|
4013
|
-
function createState(baseState, globalState, localState) {
|
|
4014
|
-
return {
|
|
4015
|
-
...createBaseState(baseState?.auth, baseState?.document),
|
|
4016
|
-
global: createGlobalState(globalState),
|
|
4017
|
-
local: createLocalState(localState)
|
|
4018
|
-
};
|
|
4019
|
-
}
|
|
4020
|
-
//#endregion
|
|
4021
|
-
export { AddChangeLogItemInputSchema, AddModuleInputSchema, AddOperationErrorInputSchema, AddOperationExampleInputSchema, AddOperationInputSchema, AddStateExampleInputSchema, AuthorSchema, BaseDocumentHeaderSchema, BaseDocumentStateSchema, CodeExampleSchema, ConfigEntrySchema, ConfigEntryTypeSchema, DeleteChangeLogItemInputSchema, DeleteModuleInputSchema, DeleteOperationErrorInputSchema, DeleteOperationExampleInputSchema, DeleteOperationInputSchema, DeleteStateExampleInputSchema, DocumentActionSchema, DocumentModelGlobalStateSchema, DocumentModelHeaderSchema, DocumentModelInputSchema, DocumentModelPHStateSchema, DocumentModelSchema, DocumentSpecificationSchema, DowngradeNotSupportedError, FileSystemError, HASH_ALGORITHM_SHA1, HASH_ALGORITHM_SHA256, HASH_ALGORITHM_SHA512, HASH_ENCODING_BASE64, HASH_ENCODING_HEX, HashMismatchError, IntegrityIssueSubType, IntegrityIssueType, InvalidActionInputError, InvalidActionInputZodError, LoadStateActionInputSchema, LoadStateActionSchema, LoadStateActionStateInputSchema, Load_StateSchema, ManifestSchema, ModuleSchema, MoveOperationInputSchema, OPERATION_NAME_PATTERN, OperationErrorSchema, OperationScopeSchema, OperationSpecificationSchema, PowerhouseModuleSchema, PowerhouseModulesSchema, PruneActionInputSchema, PruneActionSchema, PruneSchema, PublisherSchema, PwaConfigSchema, RESERVED_OPERATION_NAMES, RedoActionInputSchema, RedoActionSchema, RedoSchema, ReorderChangeLogItemsInputSchema, ReorderModuleOperationsInputSchema, ReorderModulesInputSchema, ReorderOperationErrorsInputSchema, ReorderOperationExamplesInputSchema, ReorderStateExamplesInputSchema, ScopeStateSchema, SetAuthorNameInputSchema, SetAuthorWebsiteInputSchema, SetInitialStateInputSchema, SetModelDescriptionInputSchema, SetModelExtensionInputSchema, SetModelIdInputSchema, SetModelNameInputSchema, SetModuleDescriptionInputSchema, SetModuleNameInputSchema, SetNameActionInputSchema, SetNameActionSchema, SetOperationDescriptionInputSchema, SetOperationErrorCodeInputSchema, SetOperationErrorDescriptionInputSchema, SetOperationErrorNameInputSchema, SetOperationErrorTemplateInputSchema, SetOperationNameInputSchema, SetOperationReducerInputSchema, SetOperationSchemaInputSchema, SetOperationScopeInputSchema, SetOperationTemplateInputSchema, SetPreferredEditorActionInputSchema, SetPreferredEditorActionSchema, SetStateSchemaInputSchema, Set_NameSchema, Set_PreferredEditorSchema, StateSchema, UndoActionInputSchema, UndoActionSchema, UndoSchema, UpdateChangeLogItemInputSchema, UpdateOperationExampleInputSchema, UpdateStateExampleInputSchema, ab2hex, actionContext, actionFromAction, actionSigner, actions, addChangeLogItem, addModule, addOperation, addOperationError, addOperationExample, addStateExample, addUndo, applyDeleteDocumentAction, applyUpgradeDocumentAction, assertIsDocumentModelDocument, assertIsDocumentModelState, assertModuleIdUnique, assertOperationErrorIdUnique, assertOperationExampleIdUnique, assertOperationIdUnique, attachBranch, baseActions, baseCreateDocument, baseLoadFromInput, baseLoadFromInputVersioned, baseReducer, baseSaveToFileHandle, buildOperationSignature, buildOperationSignatureMessage, buildOperationSignatureParams, buildSignedAction, checkCleanedOperationsIntegrity, checkOperationsIntegrity, computeUpgradeTransitions, createAction, createAuthState, createBaseState, createDocumentState, createGlobalState, createLocalState, createMinimalZip, createPresignedHeader, createReducer, createSignedHeader, createSignedHeaderForSigner, createState, createVerificationSigner, createZip, defaultAuthState, defaultBaseState, defaultDocumentState, defaultGlobalState, defaultLocalState, defaultPHState, definedNonNullAnySchema, deleteChangeLogItem, deleteModule, deleteOperation, deleteOperationError, deleteOperationExample, deleteStateExample, deriveOperationId, diffOperations, documentModelActions, documentModelDocumentType, documentModelFileExtension, documentModelGlobalState, documentModelHeaderReducer, documentModelInitialGlobalState, documentModelInitialLocalState, documentModelLoadFromInput, documentModelModuleReducer, documentModelOperationErrorReducer, documentModelOperationExampleReducer, documentModelOperationReducer, documentModelReducer, documentModelSaveToFileHandle, documentModelStateReducer, documentModelStateSchemaReducer, documentModelVersioningReducer, fetchFileBrowser, filterDocumentOperationsResultingState, filterDuplicatedOperations, findModuleOrThrow, findOperationErrorOrThrow, findOperationExampleOrThrow, findOperationOrThrow, garbageCollect, garbageCollectDocumentOperations, garbageCollectV2, generateId, generateMock, getAllOperationNames, getDocumentLastModified, getFileBrowser, getUnixTimestamp, groupOperationsByScope, hashBrowser, hashDocumentStateForScope, hex2ab, isDefinedNonNullAny, isDocumentAction, isDocumentModelDocument, isDocumentModelState, isNoopOperation, isReservedOperationName, isUndo, isUndoRedo, isValidOperationNameFormat, loadState, loadStateOperation, mapSkippedOperations, mapSkippedOperationsV2, merge, moveOperation, nextSkipNumber, noop, operationExampleCreators, operationFromAction, operationFromOperation, operationWithContext, operationsAreEqual, parseResultingState, precedes, prepareOperations, processUndoRedo, prune, pruneOperation, readFileBrowser, readOnly, redo, redoOperation, releaseNewVersion, removeExistingOperations, reorderChangeLogItems, reorderModuleOperations, reorderModules, reorderOperationErrors, reorderOperationExamples, reorderStateExamples, replayDocument, replayDocumentVersioned, replayOperations, reshuffleByTimestamp, reshuffleByTimestampAndIndex, setAuthorName, setAuthorWebsite, setInitialState, setModelDescription, setModelExtension, setModelId, setModelName, setModuleDescription, setModuleName, setName, setNameOperation, setOperationDescription, setOperationErrorCode, setOperationErrorDescription, setOperationErrorName, setOperationErrorTemplate, setOperationName, setOperationReducer, setOperationSchema, setOperationScope, setOperationTemplate, setPreferredEditor, setPreferredEditorOperation, setStateSchema, sign, skipHeaderOperations, sortMappedOperations, sortOperations, split, undo, undoOperation, undoOperationV2, updateChangeLogItem, updateDocument, updateHeaderRevision, updateOperationExample, updateStateExample, validateHeader, validateInitialState, validateModule, validateModuleOperation, validateModules, validateOperationName, validateOperations, validateStateSchemaName, verify, verifyOperationSignature, writeFileBrowser };
|
|
4516
|
+
export { AUTH_ACTION_TYPES, AddChangeLogItemInputSchema, AddModuleInputSchema, AddOperationErrorInputSchema, AddOperationExampleInputSchema, AddOperationInputSchema, AddStateExampleInputSchema, AuthActionNotAllowedError, AuthAlreadyInitializedError, AuthInitializerNotCreatorError, AuthPolicyNotPreservedError, AuthorSchema, BaseDocumentHeaderSchema, BaseDocumentStateSchema, CodeExampleSchema, ConfigEntrySchema, ConfigEntryTypeSchema, DeleteChangeLogItemInputSchema, DeleteModuleInputSchema, DeleteOperationErrorInputSchema, DeleteOperationExampleInputSchema, DeleteOperationInputSchema, DeleteStateExampleInputSchema, DocumentActionSchema, DocumentModelGlobalStateSchema, DocumentModelHeaderSchema, DocumentModelInputSchema, DocumentModelPHStateSchema, DocumentModelSchema, DocumentSpecificationSchema, DowngradeNotSupportedError, FileSystemError, GrantNotFoundError, GrantSchema, GroupPrincipalNotAllowedError, HASH_ALGORITHM_SHA1, HASH_ALGORITHM_SHA256, HASH_ALGORITHM_SHA512, HASH_ENCODING_BASE64, HASH_ENCODING_HEX, HashMismatchError, InitializeAuthActionInputSchema, IntegrityIssueSubType, IntegrityIssueType, InvalidActionInputError, InvalidActionInputZodError, InvalidAuthVersionError, InvalidGrantError, LoadStateActionInputSchema, LoadStateActionSchema, LoadStateActionStateInputSchema, Load_StateSchema, MAX_AUTH_GRANTS, MAX_CAPABILITY_OPERATIONS, MAX_CONDITION_DEPTH, MAX_CONDITION_NODES, MAX_SUPPORTED_AUTH_VERSION, ManifestSchema, ModuleSchema, MoveGrantActionInputSchema, MoveOperationInputSchema, OPERATION_NAME_PATTERN, OperationErrorSchema, OperationScopeSchema, OperationSpecificationSchema, PowerhouseModuleSchema, PowerhouseModulesSchema, PruneActionInputSchema, PruneActionSchema, PruneSchema, PublisherSchema, PwaConfigSchema, RESERVED_OPERATION_NAMES, RedoActionInputSchema, RedoActionSchema, RedoSchema, RemoveGrantActionInputSchema, ReorderChangeLogItemsInputSchema, ReorderModuleOperationsInputSchema, ReorderModulesInputSchema, ReorderOperationErrorsInputSchema, ReorderOperationExamplesInputSchema, ReorderStateExamplesInputSchema, ScopeStateSchema, SetAuthorNameInputSchema, SetAuthorWebsiteInputSchema, SetGrantActionInputSchema, SetInitialStateInputSchema, SetModelDescriptionInputSchema, SetModelExtensionInputSchema, SetModelIdInputSchema, SetModelNameInputSchema, SetModuleDescriptionInputSchema, SetModuleNameInputSchema, SetNameActionInputSchema, SetNameActionSchema, SetOperationDescriptionInputSchema, SetOperationErrorCodeInputSchema, SetOperationErrorDescriptionInputSchema, SetOperationErrorNameInputSchema, SetOperationErrorTemplateInputSchema, SetOperationNameInputSchema, SetOperationReducerInputSchema, SetOperationSchemaInputSchema, SetOperationScopeInputSchema, SetOperationTemplateInputSchema, SetPreferredEditorActionInputSchema, SetPreferredEditorActionSchema, SetStateSchemaInputSchema, Set_NameSchema, Set_PreferredEditorSchema, StateSchema, UndoActionInputSchema, UndoActionSchema, UndoSchema, UpdateChangeLogItemInputSchema, UpdateOperationExampleInputSchema, UpdateStateExampleInputSchema, ab2hex, actionContext, actionFromAction, actionSigner, actions, addChangeLogItem, addModule, addOperation, addOperationError, addOperationExample, addStateExample, addUndo, applyAuthAction, applyDeleteDocumentAction, applyInitializeAuthAction, applyMoveGrantAction, applyRemoveGrantAction, applySetGrantAction, applyUpgradeDocumentAction, assertAuthPreservedOnDuplicate, assertAuthScopeActionAllowed, assertIsDocumentModelDocument, assertIsDocumentModelState, assertModuleIdUnique, assertOperationErrorIdUnique, assertOperationExampleIdUnique, assertOperationIdUnique, assertValidGrant, assertValidGrantUpsert, assertValidInitialGrants, attachBranch, backfillAuthState, base58Decode, base64UrlToBytes, baseActions, baseCreateDocument, baseLoadFromInput, baseLoadFromInputVersioned, baseReducer, baseSaveToFileHandle, buildOperationSignature, buildOperationSignatureMessage, buildOperationSignatureParams, buildSignedAction, checkCleanedOperationsIntegrity, checkOperationsIntegrity, computeUpgradeTransitions, createAction, createAuthState, createBaseState, createDocumentState, createGlobalState, createLocalState, createMinimalZip, createPresignedHeader, createReducer, createSignedHeader, createSignedHeaderForSigner, createState, createVerificationSigner, createZip, decide, defaultAuthState, defaultBaseState, defaultDocumentState, defaultGlobalState, defaultLocalState, defaultPHState, definedNonNullAnySchema, deleteChangeLogItem, deleteModule, deleteOperation, deleteOperationError, deleteOperationExample, deleteStateExample, deriveOperationId, diffOperations, documentModelActions, documentModelDocumentType, documentModelFileExtension, documentModelGlobalState, documentModelHeaderReducer, documentModelInitialGlobalState, documentModelInitialLocalState, documentModelLoadFromInput, documentModelModuleReducer, documentModelOperationErrorReducer, documentModelOperationExampleReducer, documentModelOperationReducer, documentModelReducer, documentModelSaveToFileHandle, documentModelStateReducer, documentModelStateSchemaReducer, documentModelVersioningReducer, evaluateGrants, fetchFileBrowser, filterDocumentOperationsResultingState, filterDuplicatedOperations, findModuleOrThrow, findOperationErrorOrThrow, findOperationExampleOrThrow, findOperationOrThrow, garbageCollect, garbageCollectDocumentOperations, garbageCollectV2, generateId, generateMock, getAllOperationNames, getDocumentLastModified, getFileBrowser, getUnixTimestamp, grantProblem, groupDocumentType, groupOperationsByScope, hashBrowser, hashDocumentStateForScope, hex2ab, initializeAuth, isAuthAction, isDefinedNonNullAny, isDocumentAction, isDocumentCreator, isDocumentModelDocument, isDocumentModelState, isNoopOperation, isPlainValue, isReservedOperationName, isUndo, isUndoRedo, isValidOperationNameFormat, loadState, loadStateOperation, mapSkippedOperations, mapSkippedOperationsV2, merge, moveGrant, moveOperation, nextSkipNumber, noop, operationExampleCreators, operationFromAction, operationFromOperation, operationWithContext, operationsAreEqual, parseResultingState, precedes, prepareOperations, processUndoRedo, prune, pruneOperation, readFileBrowser, readOnly, redo, redoOperation, releaseNewVersion, removeExistingOperations, removeGrant, reorderChangeLogItems, reorderModuleOperations, reorderModules, reorderOperationErrors, reorderOperationExamples, reorderStateExamples, replayDocument, replayDocumentVersioned, replayOperations, reshuffleByTimestamp, reshuffleByTimestampAndIndex, setAuthorName, setAuthorWebsite, setGrant, setInitialState, setModelDescription, setModelExtension, setModelId, setModelName, setModuleDescription, setModuleName, setName, setNameOperation, setOperationDescription, setOperationErrorCode, setOperationErrorDescription, setOperationErrorName, setOperationErrorTemplate, setOperationName, setOperationReducer, setOperationSchema, setOperationScope, setOperationTemplate, setPreferredEditor, setPreferredEditorOperation, setStateSchema, sign, skipHeaderOperations, sortMappedOperations, sortOperations, split, undo, undoOperation, undoOperationV2, updateChangeLogItem, updateDocument, updateHeaderRevision, updateOperationExample, updateStateExample, validateHeader, validateInitialState, validateModule, validateModuleOperation, validateModules, validateOperationName, validateOperations, validateStateSchemaName, verify, verifyOperationSignature, writeFileBrowser };
|
|
4022
4517
|
|
|
4023
4518
|
//# sourceMappingURL=index.js.map
|