@powerhousedao/powerhouse-vetra-packages 6.2.2-dev.36 → 6.2.2-dev.38
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-Ce0yKpq-.js → entry-Db_lIhQq.js} +2 -2
- package/dist/browser/assets/{projection-entry-DwOOK_h_.js → projection-entry-DqgHaUSy.js} +4 -4
- package/dist/browser/{connect-Ecix83Q7.js → connect-BUnNjGUW.js} +872 -198
- package/dist/browser/connect-BUnNjGUW.js.map +1 -0
- package/dist/browser/{dist-D0oeNPlN.js → dist-BAJ5nRDl.js} +21 -2
- package/dist/browser/{dist-D0oeNPlN.js.map → dist-BAJ5nRDl.js.map} +1 -1
- package/dist/browser/{dist-CUh_8kqh.js → dist-BatmWBzA.js} +14 -13
- package/dist/browser/dist-BatmWBzA.js.map +1 -0
- package/dist/browser/{document-drive-CdDEdV_d.js → document-drive-D3Z9vXTQ.js} +216 -16
- package/dist/browser/document-drive-D3Z9vXTQ.js.map +1 -0
- package/dist/browser/document-models/index.js +1 -1
- package/dist/browser/{documents-j_qy61X1.js → documents-J_l59mSV.js} +19 -19
- package/dist/browser/{documents-j_qy61X1.js.map → documents-J_l59mSV.js.map} +1 -1
- package/dist/browser/editor-BLeFoOh6.js +25 -0
- package/dist/browser/editor-BLeFoOh6.js.map +1 -0
- package/dist/browser/{editor-D5lROtt4.js → editor-Bn6uXvxG.js} +9 -141
- package/dist/browser/editor-Bn6uXvxG.js.map +1 -0
- package/dist/browser/editors/document-model-editor/module.js +1 -1
- package/dist/browser/editors/generic-drive-explorer/index.js +10 -10
- 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/{node/folder-view-DPDx-QKV.mjs → browser/folder-view-DNzFnfW2.js} +53 -45
- package/dist/browser/folder-view-DNzFnfW2.js.map +1 -0
- package/dist/browser/{graphql-editor-Cynvk_pU.js → graphql-editor-DWo8N_z4.js} +6 -6
- package/dist/browser/{graphql-editor-Cynvk_pU.js.map → graphql-editor-DWo8N_z4.js.map} +1 -1
- package/dist/browser/{hooks-BgIeO-WG.js → hooks-KKcNp2X0.js} +2 -2
- package/dist/browser/{hooks-BgIeO-WG.js.map → hooks-KKcNp2X0.js.map} +1 -1
- package/dist/browser/index.js +2 -2
- package/dist/browser/{json-editor-Ia0dGnPg.js → json-editor-CEugjpFj.js} +4 -4
- package/dist/browser/{json-editor-Ia0dGnPg.js.map → json-editor-CEugjpFj.js.map} +1 -1
- package/dist/browser/{lib-7EHYE1Sh.js → lib-CiaHsAaR.js} +12 -2
- package/dist/browser/lib-CiaHsAaR.js.map +1 -0
- package/dist/browser/{linting-nOwKxGXw.js → linting-_AQWr8aE.js} +4 -4
- package/dist/browser/{linting-nOwKxGXw.js.map → linting-_AQWr8aE.js.map} +1 -1
- package/dist/browser/{schema-context-ClCYFYSx.js → schema-context-ZyeclQwy.js} +2 -2
- package/dist/browser/{schema-context-ClCYFYSx.js.map → schema-context-ZyeclQwy.js.map} +1 -1
- package/dist/browser/{state-schemas-zvqdVQZy.js → state-schemas-VrticHe4.js} +7 -7
- package/dist/browser/{state-schemas-zvqdVQZy.js.map → state-schemas-VrticHe4.js.map} +1 -1
- package/dist/node/{connect-ZK1jSpli.mjs → connect-wMkkAckX.mjs} +872 -198
- package/dist/node/connect-wMkkAckX.mjs.map +1 -0
- package/dist/node/{dist-CWzLygDa.mjs → dist-CUHBOv3P.mjs} +14 -13
- package/dist/node/dist-CUHBOv3P.mjs.map +1 -0
- package/dist/node/{dist-BeZaEP6S.mjs → dist-CzYOpeXN.mjs} +21 -2
- package/dist/node/{dist-BeZaEP6S.mjs.map → dist-CzYOpeXN.mjs.map} +1 -1
- package/dist/node/{document-drive-TRcgHnNn.mjs → document-drive-CI0J7nMj.mjs} +216 -16
- package/dist/node/document-drive-CI0J7nMj.mjs.map +1 -0
- package/dist/node/document-models/index.mjs +1 -1
- package/dist/node/{documents-Bh_lxLTV.mjs → documents-DCf53bzO.mjs} +19 -19
- package/dist/node/{documents-Bh_lxLTV.mjs.map → documents-DCf53bzO.mjs.map} +1 -1
- package/dist/node/{editor-BECSOzY6.mjs → editor-Cr-mNQca.mjs} +9 -141
- package/dist/node/editor-Cr-mNQca.mjs.map +1 -0
- package/dist/node/editor-aIeTo2EE.mjs +25 -0
- package/dist/node/editor-aIeTo2EE.mjs.map +1 -0
- package/dist/node/editors/document-model-editor/module.mjs +1 -1
- package/dist/node/editors/generic-drive-explorer/index.mjs +10 -10
- 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/{browser/folder-view-CiSnA6dd.js → node/folder-view-_x1OBYZN.mjs} +53 -45
- package/dist/node/folder-view-_x1OBYZN.mjs.map +1 -0
- package/dist/node/{graphql-editor-CllvWxH7.mjs → graphql-editor-Dd2_z5QJ.mjs} +5 -5
- package/dist/node/{graphql-editor-CllvWxH7.mjs.map → graphql-editor-Dd2_z5QJ.mjs.map} +1 -1
- package/dist/node/{hooks-B7KF2A2g.mjs → hooks-D0DcS3MV.mjs} +2 -2
- package/dist/node/{hooks-B7KF2A2g.mjs.map → hooks-D0DcS3MV.mjs.map} +1 -1
- package/dist/node/index.mjs +2 -2
- package/dist/node/{json-editor-BQz0iygc.mjs → json-editor-Dphg6ZeL.mjs} +4 -4
- package/dist/node/{json-editor-BQz0iygc.mjs.map → json-editor-Dphg6ZeL.mjs.map} +1 -1
- package/dist/node/{linting-D6drcQHM.mjs → linting-BjvRPjCY.mjs} +4 -4
- package/dist/node/{linting-D6drcQHM.mjs.map → linting-BjvRPjCY.mjs.map} +1 -1
- package/dist/node/{main-CTGoYLka.mjs → main-Db0ei9wX.mjs} +12 -2
- package/dist/node/main-Db0ei9wX.mjs.map +1 -0
- package/dist/node/{schema-context-pefmG2VW.mjs → schema-context-DL8jhi_d.mjs} +2 -2
- package/dist/node/{schema-context-pefmG2VW.mjs.map → schema-context-DL8jhi_d.mjs.map} +1 -1
- package/dist/node/{state-schemas-DHAaFwXN.mjs → state-schemas-BSLgTw2O.mjs} +7 -7
- package/dist/node/{state-schemas-DHAaFwXN.mjs.map → state-schemas-BSLgTw2O.mjs.map} +1 -1
- package/package.json +6 -6
- package/dist/browser/connect-Ecix83Q7.js.map +0 -1
- package/dist/browser/dist-CUh_8kqh.js.map +0 -1
- package/dist/browser/document-drive-CdDEdV_d.js.map +0 -1
- package/dist/browser/editor-D5lROtt4.js.map +0 -1
- package/dist/browser/editor-DS1Qw25T.js +0 -29
- package/dist/browser/editor-DS1Qw25T.js.map +0 -1
- package/dist/browser/folder-view-CiSnA6dd.js.map +0 -1
- package/dist/browser/lib-7EHYE1Sh.js.map +0 -1
- package/dist/node/connect-ZK1jSpli.mjs.map +0 -1
- package/dist/node/dist-CWzLygDa.mjs.map +0 -1
- package/dist/node/document-drive-TRcgHnNn.mjs.map +0 -1
- package/dist/node/editor-BECSOzY6.mjs.map +0 -1
- package/dist/node/editor-DU6syqHF.mjs +0 -29
- package/dist/node/editor-DU6syqHF.mjs.map +0 -1
- package/dist/node/folder-view-DPDx-QKV.mjs.map +0 -1
- package/dist/node/main-CTGoYLka.mjs.map +0 -1
|
@@ -3934,6 +3934,30 @@ var GroupPrincipalNotAllowedError = class extends Error {
|
|
|
3934
3934
|
this.grantId = grantId;
|
|
3935
3935
|
}
|
|
3936
3936
|
};
|
|
3937
|
+
/**
|
|
3938
|
+
* Thrown when a change would leave a creator-less policy with no grant
|
|
3939
|
+
* permitting execute on the auth scope. Without the creator carve-out no
|
|
3940
|
+
* subject could ever administer such a policy again.
|
|
3941
|
+
*/
|
|
3942
|
+
var AuthAdministrationLockoutError = class extends Error {
|
|
3943
|
+
grantId;
|
|
3944
|
+
constructor(grantId) {
|
|
3945
|
+
super(`Change to grant "${grantId}" would leave no reachable grant permitting execute on the auth scope: a policy with no creator must always retain one`);
|
|
3946
|
+
this.name = "AuthAdministrationLockoutError";
|
|
3947
|
+
this.grantId = grantId;
|
|
3948
|
+
}
|
|
3949
|
+
};
|
|
3950
|
+
/**
|
|
3951
|
+
* Thrown when INITIALIZE_AUTH would create a creator-less policy with no grant
|
|
3952
|
+
* permitting execute on the auth scope. Such a policy would be born with no
|
|
3953
|
+
* subject able to administer it.
|
|
3954
|
+
*/
|
|
3955
|
+
var AuthAdministrationMissingError = class extends Error {
|
|
3956
|
+
constructor() {
|
|
3957
|
+
super("Initial grants include no reachable grant permitting execute on the auth scope: a policy with no creator must always include one");
|
|
3958
|
+
this.name = "AuthAdministrationMissingError";
|
|
3959
|
+
}
|
|
3960
|
+
};
|
|
3937
3961
|
const GRANT_KEYS = new Set([
|
|
3938
3962
|
"id",
|
|
3939
3963
|
"description",
|
|
@@ -4085,15 +4109,114 @@ function assertValidGrant(grant, documentType) {
|
|
|
4085
4109
|
if (problem !== null) throw new InvalidGrantError(grantId, problem);
|
|
4086
4110
|
if (documentType === "@powerhousedao/document-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
|
|
4087
4111
|
}
|
|
4088
|
-
/**
|
|
4089
|
-
|
|
4112
|
+
/**
|
|
4113
|
+
* Validates an initial grant list: the count cap, every grant, and — on a
|
|
4114
|
+
* creator-less policy — that some grant keeps the auth scope administrable.
|
|
4115
|
+
*/
|
|
4116
|
+
function assertValidInitialGrants(grants, documentType, creator) {
|
|
4090
4117
|
if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
|
|
4091
4118
|
for (const grant of grants) assertValidGrant(grant, documentType);
|
|
4119
|
+
if (creator === void 0 && !administrationReachable(grants)) throw new AuthAdministrationMissingError();
|
|
4092
4120
|
}
|
|
4093
|
-
/**
|
|
4094
|
-
|
|
4121
|
+
/**
|
|
4122
|
+
* Validates a grant upsert: the grant itself, the count cap on append, and
|
|
4123
|
+
* administration retention. Retention is checked on an append as well as an
|
|
4124
|
+
* in-place replace, because a grant appended after the administration grant can
|
|
4125
|
+
* shadow it (evaluation is last-applicable-grant-wins) and so take
|
|
4126
|
+
* administration away without removing anything.
|
|
4127
|
+
*/
|
|
4128
|
+
function assertValidGrantUpsert(grant, existing, documentType, creator) {
|
|
4095
4129
|
assertValidGrant(grant, documentType);
|
|
4096
|
-
|
|
4130
|
+
const exists = existing.some((g) => g.id === grant.id);
|
|
4131
|
+
if (!exists && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
|
|
4132
|
+
assertAuthAdministrationRetained(creator, existing, exists ? existing.map((g) => g.id === grant.id ? grant : g) : [...existing, grant], grant.id);
|
|
4133
|
+
}
|
|
4134
|
+
/**
|
|
4135
|
+
* The request whose coverage keeps a policy administrable: a subject who may
|
|
4136
|
+
* SET_GRANT can upsert any grant, so every other repair stays reachable.
|
|
4137
|
+
*/
|
|
4138
|
+
const AUTH_ADMINISTRATION_REQUEST = {
|
|
4139
|
+
verb: "execute",
|
|
4140
|
+
scope: "auth",
|
|
4141
|
+
operation: "SET_GRANT"
|
|
4142
|
+
};
|
|
4143
|
+
/**
|
|
4144
|
+
* Whether some subject can still administer the auth scope under this grant list.
|
|
4145
|
+
*
|
|
4146
|
+
* Asks the evaluator rather than pattern-matching a single grant: evaluation is
|
|
4147
|
+
* last-applicable-grant-wins, so an allow that some later deny shadows keeps
|
|
4148
|
+
* nothing reachable even though it is still present in the list. Only anyone and
|
|
4149
|
+
* address principals are candidates, because those are the ones v1 can match at
|
|
4150
|
+
* all; a `where` condition or a group or match principal never applies.
|
|
4151
|
+
*/
|
|
4152
|
+
function administrationReachable(grants) {
|
|
4153
|
+
return grants.some((grant) => {
|
|
4154
|
+
const subject = administrationCandidate(grant);
|
|
4155
|
+
if (subject === void 0) return false;
|
|
4156
|
+
return evaluateGrantStack(grants, subject, AUTH_ADMINISTRATION_REQUEST).decision === "allow";
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
/**
|
|
4160
|
+
* The subject to test this grant with, or undefined when the grant could never
|
|
4161
|
+
* carry administration for anyone.
|
|
4162
|
+
*/
|
|
4163
|
+
function administrationCandidate(grant) {
|
|
4164
|
+
if (grant.effect !== "allow" || grant.where !== void 0 || !capabilityCovers(grant.capability, AUTH_ADMINISTRATION_REQUEST)) return;
|
|
4165
|
+
if ("address" in grant.principal) return {
|
|
4166
|
+
address: grant.principal.address,
|
|
4167
|
+
key: void 0
|
|
4168
|
+
};
|
|
4169
|
+
if ("anyone" in grant.principal) return {
|
|
4170
|
+
address: void 0,
|
|
4171
|
+
key: void 0
|
|
4172
|
+
};
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* A creator-less policy must always retain a grant permitting execute on the
|
|
4176
|
+
* auth scope; on a signed document the creator carve-out keeps administration
|
|
4177
|
+
* reachable instead. Rejects a change that takes the last such grant away. A
|
|
4178
|
+
* policy already without one is left alone: the change is not what locks it.
|
|
4179
|
+
*/
|
|
4180
|
+
function assertAuthAdministrationRetained(creator, previous, next, grantId) {
|
|
4181
|
+
if (creator !== void 0) return;
|
|
4182
|
+
if (administrationReachable(previous) && !administrationReachable(next)) throw new AuthAdministrationLockoutError(grantId);
|
|
4183
|
+
}
|
|
4184
|
+
function capabilityCovers(capability, request) {
|
|
4185
|
+
if (capability.can !== request.verb) return false;
|
|
4186
|
+
const scope = capability.scope;
|
|
4187
|
+
if (scope !== void 0 && scope !== "*" && scope !== request.scope) return false;
|
|
4188
|
+
if (capability.can === "execute") {
|
|
4189
|
+
if (capability.operation === void 0) return true;
|
|
4190
|
+
return request.operation !== void 0 && capability.operation.includes(request.operation);
|
|
4191
|
+
}
|
|
4192
|
+
return true;
|
|
4193
|
+
}
|
|
4194
|
+
function principalMatches(principal, subject) {
|
|
4195
|
+
if ("anyone" in principal) return true;
|
|
4196
|
+
if ("address" in principal) return subject.address !== void 0 && subject.address.toLowerCase() === principal.address.toLowerCase();
|
|
4197
|
+
return false;
|
|
4198
|
+
}
|
|
4199
|
+
/**
|
|
4200
|
+
* Evaluates a v1 grant stack: default deny, last applicable grant wins, and
|
|
4201
|
+
* reports which grant decided it. Group and match principals and `where`
|
|
4202
|
+
* conditions are not evaluated yet; a grant that uses any of them never applies.
|
|
4203
|
+
*/
|
|
4204
|
+
function evaluateGrantStack(grants, subject, request) {
|
|
4205
|
+
let applicable;
|
|
4206
|
+
for (const grant of grants) {
|
|
4207
|
+
if (grant.where !== void 0) continue;
|
|
4208
|
+
if (capabilityCovers(grant.capability, request) && principalMatches(grant.principal, subject)) applicable = grant;
|
|
4209
|
+
}
|
|
4210
|
+
if (applicable === void 0) return {
|
|
4211
|
+
decision: "deny",
|
|
4212
|
+
refusal: "no-applicable-grant"
|
|
4213
|
+
};
|
|
4214
|
+
if (applicable.effect === "deny") return {
|
|
4215
|
+
decision: "deny",
|
|
4216
|
+
refusal: "denied-by-grant",
|
|
4217
|
+
grantId: applicable.id
|
|
4218
|
+
};
|
|
4219
|
+
return { decision: "allow" };
|
|
4097
4220
|
}
|
|
4098
4221
|
const documentModelFileExtension = "phdm";
|
|
4099
4222
|
const documentModelInitialLocalState = {};
|
|
@@ -4830,6 +4953,8 @@ function isDocumentCreator(creatorKey, signerKey) {
|
|
|
4830
4953
|
* (version 0). The input version is the policy language version and must be an
|
|
4831
4954
|
* integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
|
|
4832
4955
|
* document it must be signed by the document creator (`header.sig.publicKey`).
|
|
4956
|
+
* A creator-less policy must include a grant permitting execute on the auth
|
|
4957
|
+
* scope, or it would be born locked out.
|
|
4833
4958
|
*/
|
|
4834
4959
|
function applyInitializeAuthAction(document, action) {
|
|
4835
4960
|
assertActionInputShape(action.input);
|
|
@@ -4837,12 +4962,12 @@ function applyInitializeAuthAction(document, action) {
|
|
|
4837
4962
|
if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
|
|
4838
4963
|
if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
|
|
4839
4964
|
if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
4840
|
-
assertValidInitialGrants(grants, document.header.documentType);
|
|
4841
4965
|
const creatorKey = document.header.sig.publicKey;
|
|
4842
4966
|
const signerKey = action.context?.signer?.app.key;
|
|
4843
4967
|
const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
|
|
4844
4968
|
if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
|
|
4845
4969
|
const creator = hasCreator ? signerKey : void 0;
|
|
4970
|
+
assertValidInitialGrants(grants, document.header.documentType, creator);
|
|
4846
4971
|
return {
|
|
4847
4972
|
...document,
|
|
4848
4973
|
state: {
|
|
@@ -4863,32 +4988,42 @@ function applySetGrantAction(document, action) {
|
|
|
4863
4988
|
assertActionInputShape(action.input);
|
|
4864
4989
|
const { grant } = action.input;
|
|
4865
4990
|
const grants = document.state.auth.grants;
|
|
4866
|
-
assertValidGrantUpsert(grant, grants, document.header.documentType);
|
|
4991
|
+
assertValidGrantUpsert(grant, grants, document.header.documentType, document.state.auth.creator);
|
|
4867
4992
|
return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
|
|
4868
4993
|
}
|
|
4869
|
-
/**
|
|
4994
|
+
/**
|
|
4995
|
+
* Removes a grant by id; throws if the id is not present or if the removal
|
|
4996
|
+
* would leave a creator-less policy with no auth-administration grant.
|
|
4997
|
+
*/
|
|
4870
4998
|
function applyRemoveGrantAction(document, action) {
|
|
4871
4999
|
assertActionInputShape(action.input);
|
|
4872
5000
|
const { id } = action.input;
|
|
4873
|
-
const grants = document.state.auth
|
|
5001
|
+
const { grants, creator } = document.state.auth;
|
|
4874
5002
|
if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
|
|
4875
|
-
|
|
5003
|
+
const next = grants.filter((g) => g.id !== id);
|
|
5004
|
+
assertAuthAdministrationRetained(creator, grants, next, id);
|
|
5005
|
+
return withGrants(document, next);
|
|
4876
5006
|
}
|
|
4877
5007
|
/**
|
|
4878
5008
|
* Moves a grant by id to a new index. Order is load-bearing (the last
|
|
4879
5009
|
* applicable grant wins), so the relative order of the other grants is kept.
|
|
4880
5010
|
* The target index is clamped to the valid range; an unknown id throws.
|
|
5011
|
+
*
|
|
5012
|
+
* Order alone decides which grant wins, so a move can take administration away
|
|
5013
|
+
* without changing the list's contents. It carries the same retention rule as
|
|
5014
|
+
* the two mutation paths.
|
|
4881
5015
|
*/
|
|
4882
5016
|
function applyMoveGrantAction(document, action) {
|
|
4883
5017
|
assertActionInputShape(action.input);
|
|
4884
5018
|
const { id, index } = action.input;
|
|
4885
|
-
const grants = document.state.auth
|
|
5019
|
+
const { grants, creator } = document.state.auth;
|
|
4886
5020
|
const from = grants.findIndex((g) => g.id === id);
|
|
4887
5021
|
if (from === -1) throw new GrantNotFoundError(id);
|
|
4888
5022
|
const next = [...grants];
|
|
4889
5023
|
const [moved] = next.splice(from, 1);
|
|
4890
5024
|
const to = Math.max(0, Math.min(index, next.length));
|
|
4891
5025
|
next.splice(to, 0, moved);
|
|
5026
|
+
assertAuthAdministrationRetained(creator, grants, next, id);
|
|
4892
5027
|
return withGrants(document, next);
|
|
4893
5028
|
}
|
|
4894
5029
|
/**
|
|
@@ -4914,6 +5049,42 @@ function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
|
|
|
4914
5049
|
if (!source || source.version === 0) return;
|
|
4915
5050
|
if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
|
|
4916
5051
|
}
|
|
5052
|
+
/**
|
|
5053
|
+
* The auth scope a state snapshot may install, given the policy already there.
|
|
5054
|
+
*
|
|
5055
|
+
* `applyAuthAction` is the validated door onto `state.auth`, but a whole-state
|
|
5056
|
+
* snapshot (UPGRADE_DOCUMENT's `initialState`, LOAD_STATE's `data`) replaces the
|
|
5057
|
+
* scope wholesale and is authorized as a `document`-scope write. Without this,
|
|
5058
|
+
* a subject holding `execute` on `document` and no auth grant at all can install
|
|
5059
|
+
* a policy of its choosing, name itself `creator` (which exempts the policy from
|
|
5060
|
+
* the retention rule for good), or wipe an existing policy by carrying the
|
|
5061
|
+
* default uninitialized one.
|
|
5062
|
+
*
|
|
5063
|
+
* Three cases:
|
|
5064
|
+
*
|
|
5065
|
+
* - the snapshot carries no policy, or an uninitialized one: the document
|
|
5066
|
+
* keeps the policy it has, so a default-state upgrade cannot reset it;
|
|
5067
|
+
* - the document is uninitialized and the snapshot carries a policy: the
|
|
5068
|
+
* policy is installed after the same validation genesis applies, so it
|
|
5069
|
+
* cannot be born locked out;
|
|
5070
|
+
* - both carry a policy: they must agree. A duplicate preserves its source's
|
|
5071
|
+
* policy (see {@link assertAuthPreservedOnDuplicate}), and anything else is
|
|
5072
|
+
* an attempt to replace one policy with another.
|
|
5073
|
+
*/
|
|
5074
|
+
function resolveSnapshotAuth(documentId, documentType, current, incoming) {
|
|
5075
|
+
const currentAuth = current ?? createAuthState({
|
|
5076
|
+
version: 0,
|
|
5077
|
+
grants: []
|
|
5078
|
+
});
|
|
5079
|
+
if (!incoming || !incoming.version) return currentAuth;
|
|
5080
|
+
if (currentAuth.version !== 0) {
|
|
5081
|
+
if (stringify$1(incoming) !== stringify$1(currentAuth)) throw new AuthPolicyNotPreservedError(documentId);
|
|
5082
|
+
return incoming;
|
|
5083
|
+
}
|
|
5084
|
+
if (!Array.isArray(incoming.grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
5085
|
+
assertValidInitialGrants(incoming.grants, documentType, incoming.creator);
|
|
5086
|
+
return incoming;
|
|
5087
|
+
}
|
|
4917
5088
|
/** UNDO, REDO and PRUNE are rejected on the auth scope. */
|
|
4918
5089
|
function assertAuthScopeActionAllowed(action) {
|
|
4919
5090
|
if (action.scope === "auth" && [
|
|
@@ -4922,6 +5093,12 @@ function assertAuthScopeActionAllowed(action) {
|
|
|
4922
5093
|
"PRUNE"
|
|
4923
5094
|
].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
|
|
4924
5095
|
}
|
|
5096
|
+
/**
|
|
5097
|
+
* True iff authorization rejected the action.
|
|
5098
|
+
*/
|
|
5099
|
+
function isDenied(operation) {
|
|
5100
|
+
return operation.deniedReason !== void 0;
|
|
5101
|
+
}
|
|
4925
5102
|
const BaseDocumentHeaderSchema = object({
|
|
4926
5103
|
id: string(),
|
|
4927
5104
|
name: string(),
|
|
@@ -5104,6 +5281,22 @@ function garbageCollectV2(sortedOperations) {
|
|
|
5104
5281
|
const defaultCreateState = (state) => {
|
|
5105
5282
|
return state;
|
|
5106
5283
|
};
|
|
5284
|
+
/**
|
|
5285
|
+
* Records an operation in the history without applying it, which is what a
|
|
5286
|
+
* denied operation needs: it occupies its index and contributes no state.
|
|
5287
|
+
*
|
|
5288
|
+
* The scope defaults to the action's own, and is passed explicitly by a rebuild
|
|
5289
|
+
* that is walking one stream and does not want to trust the action's copy.
|
|
5290
|
+
*/
|
|
5291
|
+
function appendWithoutApplying(document, operation, scope = operation.action.scope) {
|
|
5292
|
+
return {
|
|
5293
|
+
...document,
|
|
5294
|
+
operations: {
|
|
5295
|
+
...document.operations,
|
|
5296
|
+
[scope]: [...document.operations[scope] ?? [], operation]
|
|
5297
|
+
}
|
|
5298
|
+
};
|
|
5299
|
+
}
|
|
5107
5300
|
function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
|
|
5108
5301
|
const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
|
|
5109
5302
|
const backfilledInitialState = backfillAuthState(initialState);
|
|
@@ -5148,6 +5341,7 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
|
|
|
5148
5341
|
};
|
|
5149
5342
|
let result = document;
|
|
5150
5343
|
if (operationsToReplay.length) result = operationsToReplay.reduce((document, operation) => {
|
|
5344
|
+
if (isDenied(operation)) return appendWithoutApplying(document, operation);
|
|
5151
5345
|
return reducer(document, operation.action, dispatch, {
|
|
5152
5346
|
ignoreSkipOperations: true,
|
|
5153
5347
|
checkHashes,
|
|
@@ -5429,13 +5623,15 @@ function redoOperation(document, action, skip) {
|
|
|
5429
5623
|
});
|
|
5430
5624
|
}
|
|
5431
5625
|
function loadStateOperation(document, action) {
|
|
5626
|
+
const loaded = backfillAuthState(action.state.data);
|
|
5627
|
+
loaded.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, loaded.auth);
|
|
5432
5628
|
return {
|
|
5433
5629
|
...document,
|
|
5434
5630
|
header: {
|
|
5435
5631
|
...document.header,
|
|
5436
5632
|
name: action.state.name
|
|
5437
5633
|
},
|
|
5438
|
-
state:
|
|
5634
|
+
state: loaded
|
|
5439
5635
|
};
|
|
5440
5636
|
}
|
|
5441
5637
|
function replayOperations(initialState, clearedOperations, stateReducer, header, dispatch, documentReducer = baseReducer, skipHeaderOperations = {}, options) {
|
|
@@ -6457,10 +6653,12 @@ function applyInitialState(document, action) {
|
|
|
6457
6653
|
const input = action.input;
|
|
6458
6654
|
const newState = input.initialState || input.state;
|
|
6459
6655
|
if (newState) {
|
|
6460
|
-
|
|
6656
|
+
const merged = backfillAuthState({
|
|
6461
6657
|
...document.state,
|
|
6462
6658
|
...newState
|
|
6463
6659
|
});
|
|
6660
|
+
merged.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, merged.auth);
|
|
6661
|
+
document.state = merged;
|
|
6464
6662
|
document.initialState = document.state;
|
|
6465
6663
|
}
|
|
6466
6664
|
}
|
|
@@ -6638,7 +6836,8 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6638
6836
|
const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
|
|
6639
6837
|
const segOps = ops.slice(segStart, segEnd);
|
|
6640
6838
|
for (const op of segOps) {
|
|
6641
|
-
document =
|
|
6839
|
+
if (isDenied(op)) document = appendWithoutApplying(document, op, s);
|
|
6840
|
+
else document = reducer(document, op.action, dispatch, {
|
|
6642
6841
|
ignoreSkipOperations: true,
|
|
6643
6842
|
checkHashes,
|
|
6644
6843
|
skipIndexValidation,
|
|
@@ -6655,6 +6854,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6655
6854
|
if (!spineOp) continue;
|
|
6656
6855
|
const spineActionType = spineOp.action.type;
|
|
6657
6856
|
if (spineActionType === "CREATE_DOCUMENT" || spineActionType === "UPGRADE_DOCUMENT") continue;
|
|
6857
|
+
if (isDenied(spineOp)) continue;
|
|
6658
6858
|
if (spineActionType === "DELETE_DOCUMENT") document = applyDeleteDocumentAction(document, spineOp.action);
|
|
6659
6859
|
else document = reducer(document, spineOp.action, dispatch, {
|
|
6660
6860
|
ignoreSkipOperations: true,
|
|
@@ -7906,6 +8106,6 @@ const driveDocumentModelModule = {
|
|
|
7906
8106
|
}
|
|
7907
8107
|
};
|
|
7908
8108
|
//#endregion
|
|
7909
|
-
export {
|
|
8109
|
+
export { generateId as $, documentModelDocumentType as A, setModelId as B, createReducer as C, deleteModule as D, defaultBaseState as E, setAuthorName as F, setOperationErrorName as G, setModuleName as H, setAuthorWebsite as I, setStateSchema as J, setOperationName as K, setInitialState as L, isDocumentAction as M, redo as N, deleteOperation as O, replayDocumentVersioned as P, validateStateSchemaName as Q, setModelDescription as R, createPresignedHeader as S, createZip as T, setName as U, setModelName as V, setOperationDescription as W, validateInitialState as X, undo as Y, validateModules as Z, baseCreateDocument as _, handleTargetNameCollisions as a, baseSaveToFileHandle as b, isValidName as c, documentModelDocumentModelModule as d, logger as f, assertAuthPreservedOnDuplicate as g, addOperationError as h, generateNodesCopy as i, hashDocumentStateForScope as j, deleteOperationError as k, moveNode as l, addOperation as m, copyNode as n, isFileNode as o, addModule as p, setOperationSchema as q, driveDocumentModelModule as r, isFolderNode as s, addFolder as t, updateNode as u, baseLoadFromInput as v, createState as w, buildSignedAction as x, baseLoadFromInputVersioned as y, setModelExtension as z };
|
|
7910
8110
|
|
|
7911
|
-
//# sourceMappingURL=document-drive-
|
|
8111
|
+
//# sourceMappingURL=document-drive-D3Z9vXTQ.js.map
|