@powerhousedao/powerhouse-vetra-packages 6.2.2-dev.37 → 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-Bo9VhPiW.js → connect-BUnNjGUW.js} +4 -4
- package/dist/browser/{connect-Bo9VhPiW.js.map → connect-BUnNjGUW.js.map} +1 -1
- package/dist/browser/{dist-CjTPkGv0.js → dist-BatmWBzA.js} +10 -5
- package/dist/browser/dist-BatmWBzA.js.map +1 -0
- package/dist/browser/{document-drive-7ZETDjDW.js → document-drive-D3Z9vXTQ.js} +215 -15
- 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-DdXTn8Bb.js → editor-BLeFoOh6.js} +5 -5
- package/dist/browser/{editor-DdXTn8Bb.js.map → editor-BLeFoOh6.js.map} +1 -1
- package/dist/browser/{editor-BMcvrau8.js → editor-Bn6uXvxG.js} +8 -8
- package/dist/browser/{editor-BMcvrau8.js.map → editor-Bn6uXvxG.js.map} +1 -1
- 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/browser/{folder-view-NvF6blmO.js → folder-view-DNzFnfW2.js} +3 -3
- package/dist/browser/{folder-view-NvF6blmO.js.map → folder-view-DNzFnfW2.js.map} +1 -1
- package/dist/browser/{graphql-editor-DZ9dahN7.js → graphql-editor-DWo8N_z4.js} +6 -6
- package/dist/browser/{graphql-editor-DZ9dahN7.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-CEONvejU.js → json-editor-CEugjpFj.js} +4 -4
- package/dist/browser/{json-editor-CEONvejU.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-B6pEyjjP.js → state-schemas-VrticHe4.js} +6 -6
- package/dist/browser/{state-schemas-B6pEyjjP.js.map → state-schemas-VrticHe4.js.map} +1 -1
- package/dist/node/{connect-DyNHqED-.mjs → connect-wMkkAckX.mjs} +4 -4
- package/dist/node/{connect-DyNHqED-.mjs.map → connect-wMkkAckX.mjs.map} +1 -1
- package/dist/node/{dist-CFNjGFP-.mjs → dist-CUHBOv3P.mjs} +10 -5
- package/dist/node/dist-CUHBOv3P.mjs.map +1 -0
- package/dist/node/{document-drive-BTZnoCCz.mjs → document-drive-CI0J7nMj.mjs} +215 -15
- 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-B21QNhzm.mjs → editor-Cr-mNQca.mjs} +8 -8
- package/dist/node/{editor-B21QNhzm.mjs.map → editor-Cr-mNQca.mjs.map} +1 -1
- package/dist/node/{editor-caNg0yOU.mjs → editor-aIeTo2EE.mjs} +5 -5
- package/dist/node/{editor-caNg0yOU.mjs.map → editor-aIeTo2EE.mjs.map} +1 -1
- 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/node/{folder-view-C6auhJCh.mjs → folder-view-_x1OBYZN.mjs} +3 -3
- package/dist/node/{folder-view-C6auhJCh.mjs.map → folder-view-_x1OBYZN.mjs.map} +1 -1
- package/dist/node/{graphql-editor-De6sk7oj.mjs → graphql-editor-Dd2_z5QJ.mjs} +5 -5
- package/dist/node/{graphql-editor-De6sk7oj.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-h2h_9Utl.mjs → json-editor-Dphg6ZeL.mjs} +4 -4
- package/dist/node/{json-editor-h2h_9Utl.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-CN2lpYg-.mjs → state-schemas-BSLgTw2O.mjs} +6 -6
- package/dist/node/{state-schemas-CN2lpYg-.mjs.map → state-schemas-BSLgTw2O.mjs.map} +1 -1
- package/package.json +6 -6
- package/dist/browser/dist-CjTPkGv0.js.map +0 -1
- package/dist/browser/document-drive-7ZETDjDW.js.map +0 -1
- package/dist/browser/lib-7EHYE1Sh.js.map +0 -1
- package/dist/node/dist-CFNjGFP-.mjs.map +0 -1
- package/dist/node/document-drive-BTZnoCCz.mjs.map +0 -1
- package/dist/node/main-CTGoYLka.mjs.map +0 -1
|
@@ -3951,6 +3951,30 @@ var GroupPrincipalNotAllowedError = class extends Error {
|
|
|
3951
3951
|
this.grantId = grantId;
|
|
3952
3952
|
}
|
|
3953
3953
|
};
|
|
3954
|
+
/**
|
|
3955
|
+
* Thrown when a change would leave a creator-less policy with no grant
|
|
3956
|
+
* permitting execute on the auth scope. Without the creator carve-out no
|
|
3957
|
+
* subject could ever administer such a policy again.
|
|
3958
|
+
*/
|
|
3959
|
+
var AuthAdministrationLockoutError = class extends Error {
|
|
3960
|
+
grantId;
|
|
3961
|
+
constructor(grantId) {
|
|
3962
|
+
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`);
|
|
3963
|
+
this.name = "AuthAdministrationLockoutError";
|
|
3964
|
+
this.grantId = grantId;
|
|
3965
|
+
}
|
|
3966
|
+
};
|
|
3967
|
+
/**
|
|
3968
|
+
* Thrown when INITIALIZE_AUTH would create a creator-less policy with no grant
|
|
3969
|
+
* permitting execute on the auth scope. Such a policy would be born with no
|
|
3970
|
+
* subject able to administer it.
|
|
3971
|
+
*/
|
|
3972
|
+
var AuthAdministrationMissingError = class extends Error {
|
|
3973
|
+
constructor() {
|
|
3974
|
+
super("Initial grants include no reachable grant permitting execute on the auth scope: a policy with no creator must always include one");
|
|
3975
|
+
this.name = "AuthAdministrationMissingError";
|
|
3976
|
+
}
|
|
3977
|
+
};
|
|
3954
3978
|
const GRANT_KEYS = new Set([
|
|
3955
3979
|
"id",
|
|
3956
3980
|
"description",
|
|
@@ -4102,15 +4126,114 @@ function assertValidGrant(grant, documentType) {
|
|
|
4102
4126
|
if (problem !== null) throw new InvalidGrantError(grantId, problem);
|
|
4103
4127
|
if (documentType === "@powerhousedao/document-group" && "group" in grant.principal) throw new GroupPrincipalNotAllowedError(grantId);
|
|
4104
4128
|
}
|
|
4105
|
-
/**
|
|
4106
|
-
|
|
4129
|
+
/**
|
|
4130
|
+
* Validates an initial grant list: the count cap, every grant, and — on a
|
|
4131
|
+
* creator-less policy — that some grant keeps the auth scope administrable.
|
|
4132
|
+
*/
|
|
4133
|
+
function assertValidInitialGrants(grants, documentType, creator) {
|
|
4107
4134
|
if (grants.length > 100) throw new InvalidGrantError("", `policy exceeds 100 grants`);
|
|
4108
4135
|
for (const grant of grants) assertValidGrant(grant, documentType);
|
|
4136
|
+
if (creator === void 0 && !administrationReachable(grants)) throw new AuthAdministrationMissingError();
|
|
4109
4137
|
}
|
|
4110
|
-
/**
|
|
4111
|
-
|
|
4138
|
+
/**
|
|
4139
|
+
* Validates a grant upsert: the grant itself, the count cap on append, and
|
|
4140
|
+
* administration retention. Retention is checked on an append as well as an
|
|
4141
|
+
* in-place replace, because a grant appended after the administration grant can
|
|
4142
|
+
* shadow it (evaluation is last-applicable-grant-wins) and so take
|
|
4143
|
+
* administration away without removing anything.
|
|
4144
|
+
*/
|
|
4145
|
+
function assertValidGrantUpsert(grant, existing, documentType, creator) {
|
|
4112
4146
|
assertValidGrant(grant, documentType);
|
|
4113
|
-
|
|
4147
|
+
const exists = existing.some((g) => g.id === grant.id);
|
|
4148
|
+
if (!exists && existing.length >= 100) throw new InvalidGrantError(grant.id, `policy exceeds 100 grants`);
|
|
4149
|
+
assertAuthAdministrationRetained(creator, existing, exists ? existing.map((g) => g.id === grant.id ? grant : g) : [...existing, grant], grant.id);
|
|
4150
|
+
}
|
|
4151
|
+
/**
|
|
4152
|
+
* The request whose coverage keeps a policy administrable: a subject who may
|
|
4153
|
+
* SET_GRANT can upsert any grant, so every other repair stays reachable.
|
|
4154
|
+
*/
|
|
4155
|
+
const AUTH_ADMINISTRATION_REQUEST = {
|
|
4156
|
+
verb: "execute",
|
|
4157
|
+
scope: "auth",
|
|
4158
|
+
operation: "SET_GRANT"
|
|
4159
|
+
};
|
|
4160
|
+
/**
|
|
4161
|
+
* Whether some subject can still administer the auth scope under this grant list.
|
|
4162
|
+
*
|
|
4163
|
+
* Asks the evaluator rather than pattern-matching a single grant: evaluation is
|
|
4164
|
+
* last-applicable-grant-wins, so an allow that some later deny shadows keeps
|
|
4165
|
+
* nothing reachable even though it is still present in the list. Only anyone and
|
|
4166
|
+
* address principals are candidates, because those are the ones v1 can match at
|
|
4167
|
+
* all; a `where` condition or a group or match principal never applies.
|
|
4168
|
+
*/
|
|
4169
|
+
function administrationReachable(grants) {
|
|
4170
|
+
return grants.some((grant) => {
|
|
4171
|
+
const subject = administrationCandidate(grant);
|
|
4172
|
+
if (subject === void 0) return false;
|
|
4173
|
+
return evaluateGrantStack(grants, subject, AUTH_ADMINISTRATION_REQUEST).decision === "allow";
|
|
4174
|
+
});
|
|
4175
|
+
}
|
|
4176
|
+
/**
|
|
4177
|
+
* The subject to test this grant with, or undefined when the grant could never
|
|
4178
|
+
* carry administration for anyone.
|
|
4179
|
+
*/
|
|
4180
|
+
function administrationCandidate(grant) {
|
|
4181
|
+
if (grant.effect !== "allow" || grant.where !== void 0 || !capabilityCovers(grant.capability, AUTH_ADMINISTRATION_REQUEST)) return;
|
|
4182
|
+
if ("address" in grant.principal) return {
|
|
4183
|
+
address: grant.principal.address,
|
|
4184
|
+
key: void 0
|
|
4185
|
+
};
|
|
4186
|
+
if ("anyone" in grant.principal) return {
|
|
4187
|
+
address: void 0,
|
|
4188
|
+
key: void 0
|
|
4189
|
+
};
|
|
4190
|
+
}
|
|
4191
|
+
/**
|
|
4192
|
+
* A creator-less policy must always retain a grant permitting execute on the
|
|
4193
|
+
* auth scope; on a signed document the creator carve-out keeps administration
|
|
4194
|
+
* reachable instead. Rejects a change that takes the last such grant away. A
|
|
4195
|
+
* policy already without one is left alone: the change is not what locks it.
|
|
4196
|
+
*/
|
|
4197
|
+
function assertAuthAdministrationRetained(creator, previous, next, grantId) {
|
|
4198
|
+
if (creator !== void 0) return;
|
|
4199
|
+
if (administrationReachable(previous) && !administrationReachable(next)) throw new AuthAdministrationLockoutError(grantId);
|
|
4200
|
+
}
|
|
4201
|
+
function capabilityCovers(capability, request) {
|
|
4202
|
+
if (capability.can !== request.verb) return false;
|
|
4203
|
+
const scope = capability.scope;
|
|
4204
|
+
if (scope !== void 0 && scope !== "*" && scope !== request.scope) return false;
|
|
4205
|
+
if (capability.can === "execute") {
|
|
4206
|
+
if (capability.operation === void 0) return true;
|
|
4207
|
+
return request.operation !== void 0 && capability.operation.includes(request.operation);
|
|
4208
|
+
}
|
|
4209
|
+
return true;
|
|
4210
|
+
}
|
|
4211
|
+
function principalMatches(principal, subject) {
|
|
4212
|
+
if ("anyone" in principal) return true;
|
|
4213
|
+
if ("address" in principal) return subject.address !== void 0 && subject.address.toLowerCase() === principal.address.toLowerCase();
|
|
4214
|
+
return false;
|
|
4215
|
+
}
|
|
4216
|
+
/**
|
|
4217
|
+
* Evaluates a v1 grant stack: default deny, last applicable grant wins, and
|
|
4218
|
+
* reports which grant decided it. Group and match principals and `where`
|
|
4219
|
+
* conditions are not evaluated yet; a grant that uses any of them never applies.
|
|
4220
|
+
*/
|
|
4221
|
+
function evaluateGrantStack(grants, subject, request) {
|
|
4222
|
+
let applicable;
|
|
4223
|
+
for (const grant of grants) {
|
|
4224
|
+
if (grant.where !== void 0) continue;
|
|
4225
|
+
if (capabilityCovers(grant.capability, request) && principalMatches(grant.principal, subject)) applicable = grant;
|
|
4226
|
+
}
|
|
4227
|
+
if (applicable === void 0) return {
|
|
4228
|
+
decision: "deny",
|
|
4229
|
+
refusal: "no-applicable-grant"
|
|
4230
|
+
};
|
|
4231
|
+
if (applicable.effect === "deny") return {
|
|
4232
|
+
decision: "deny",
|
|
4233
|
+
refusal: "denied-by-grant",
|
|
4234
|
+
grantId: applicable.id
|
|
4235
|
+
};
|
|
4236
|
+
return { decision: "allow" };
|
|
4114
4237
|
}
|
|
4115
4238
|
const documentModelFileExtension = "phdm";
|
|
4116
4239
|
const documentModelInitialLocalState = {};
|
|
@@ -4847,6 +4970,8 @@ function isDocumentCreator(creatorKey, signerKey) {
|
|
|
4847
4970
|
* (version 0). The input version is the policy language version and must be an
|
|
4848
4971
|
* integer >= 1; 0 is reserved for the uninitialized state. On a signed-header
|
|
4849
4972
|
* document it must be signed by the document creator (`header.sig.publicKey`).
|
|
4973
|
+
* A creator-less policy must include a grant permitting execute on the auth
|
|
4974
|
+
* scope, or it would be born locked out.
|
|
4850
4975
|
*/
|
|
4851
4976
|
function applyInitializeAuthAction(document, action) {
|
|
4852
4977
|
assertActionInputShape(action.input);
|
|
@@ -4854,12 +4979,12 @@ function applyInitializeAuthAction(document, action) {
|
|
|
4854
4979
|
if (!Number.isInteger(version) || version < 1) throw new InvalidAuthVersionError(document.header.id, version);
|
|
4855
4980
|
if (document.state.auth.version !== 0) throw new AuthAlreadyInitializedError(document.header.id);
|
|
4856
4981
|
if (!Array.isArray(grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
4857
|
-
assertValidInitialGrants(grants, document.header.documentType);
|
|
4858
4982
|
const creatorKey = document.header.sig.publicKey;
|
|
4859
4983
|
const signerKey = action.context?.signer?.app.key;
|
|
4860
4984
|
const hasCreator = Boolean(creatorKey.kty || creatorKey.x || creatorKey.y);
|
|
4861
4985
|
if (hasCreator && !isDocumentCreator(creatorKey, signerKey)) throw new AuthInitializerNotCreatorError(document.header.id);
|
|
4862
4986
|
const creator = hasCreator ? signerKey : void 0;
|
|
4987
|
+
assertValidInitialGrants(grants, document.header.documentType, creator);
|
|
4863
4988
|
return {
|
|
4864
4989
|
...document,
|
|
4865
4990
|
state: {
|
|
@@ -4880,32 +5005,42 @@ function applySetGrantAction(document, action) {
|
|
|
4880
5005
|
assertActionInputShape(action.input);
|
|
4881
5006
|
const { grant } = action.input;
|
|
4882
5007
|
const grants = document.state.auth.grants;
|
|
4883
|
-
assertValidGrantUpsert(grant, grants, document.header.documentType);
|
|
5008
|
+
assertValidGrantUpsert(grant, grants, document.header.documentType, document.state.auth.creator);
|
|
4884
5009
|
return withGrants(document, grants.some((g) => g.id === grant.id) ? grants.map((g) => g.id === grant.id ? grant : g) : [...grants, grant]);
|
|
4885
5010
|
}
|
|
4886
|
-
/**
|
|
5011
|
+
/**
|
|
5012
|
+
* Removes a grant by id; throws if the id is not present or if the removal
|
|
5013
|
+
* would leave a creator-less policy with no auth-administration grant.
|
|
5014
|
+
*/
|
|
4887
5015
|
function applyRemoveGrantAction(document, action) {
|
|
4888
5016
|
assertActionInputShape(action.input);
|
|
4889
5017
|
const { id } = action.input;
|
|
4890
|
-
const grants = document.state.auth
|
|
5018
|
+
const { grants, creator } = document.state.auth;
|
|
4891
5019
|
if (!grants.some((g) => g.id === id)) throw new GrantNotFoundError(id);
|
|
4892
|
-
|
|
5020
|
+
const next = grants.filter((g) => g.id !== id);
|
|
5021
|
+
assertAuthAdministrationRetained(creator, grants, next, id);
|
|
5022
|
+
return withGrants(document, next);
|
|
4893
5023
|
}
|
|
4894
5024
|
/**
|
|
4895
5025
|
* Moves a grant by id to a new index. Order is load-bearing (the last
|
|
4896
5026
|
* applicable grant wins), so the relative order of the other grants is kept.
|
|
4897
5027
|
* The target index is clamped to the valid range; an unknown id throws.
|
|
5028
|
+
*
|
|
5029
|
+
* Order alone decides which grant wins, so a move can take administration away
|
|
5030
|
+
* without changing the list's contents. It carries the same retention rule as
|
|
5031
|
+
* the two mutation paths.
|
|
4898
5032
|
*/
|
|
4899
5033
|
function applyMoveGrantAction(document, action) {
|
|
4900
5034
|
assertActionInputShape(action.input);
|
|
4901
5035
|
const { id, index } = action.input;
|
|
4902
|
-
const grants = document.state.auth
|
|
5036
|
+
const { grants, creator } = document.state.auth;
|
|
4903
5037
|
const from = grants.findIndex((g) => g.id === id);
|
|
4904
5038
|
if (from === -1) throw new GrantNotFoundError(id);
|
|
4905
5039
|
const next = [...grants];
|
|
4906
5040
|
const [moved] = next.splice(from, 1);
|
|
4907
5041
|
const to = Math.max(0, Math.min(index, next.length));
|
|
4908
5042
|
next.splice(to, 0, moved);
|
|
5043
|
+
assertAuthAdministrationRetained(creator, grants, next, id);
|
|
4909
5044
|
return withGrants(document, next);
|
|
4910
5045
|
}
|
|
4911
5046
|
/**
|
|
@@ -4931,6 +5066,42 @@ function assertAuthPreservedOnDuplicate(documentId, source, duplicated) {
|
|
|
4931
5066
|
if (!source || source.version === 0) return;
|
|
4932
5067
|
if (duplicated === void 0 || duplicated.version !== source.version || duplicated.creator !== source.creator) throw new AuthPolicyNotPreservedError(documentId);
|
|
4933
5068
|
}
|
|
5069
|
+
/**
|
|
5070
|
+
* The auth scope a state snapshot may install, given the policy already there.
|
|
5071
|
+
*
|
|
5072
|
+
* `applyAuthAction` is the validated door onto `state.auth`, but a whole-state
|
|
5073
|
+
* snapshot (UPGRADE_DOCUMENT's `initialState`, LOAD_STATE's `data`) replaces the
|
|
5074
|
+
* scope wholesale and is authorized as a `document`-scope write. Without this,
|
|
5075
|
+
* a subject holding `execute` on `document` and no auth grant at all can install
|
|
5076
|
+
* a policy of its choosing, name itself `creator` (which exempts the policy from
|
|
5077
|
+
* the retention rule for good), or wipe an existing policy by carrying the
|
|
5078
|
+
* default uninitialized one.
|
|
5079
|
+
*
|
|
5080
|
+
* Three cases:
|
|
5081
|
+
*
|
|
5082
|
+
* - the snapshot carries no policy, or an uninitialized one: the document
|
|
5083
|
+
* keeps the policy it has, so a default-state upgrade cannot reset it;
|
|
5084
|
+
* - the document is uninitialized and the snapshot carries a policy: the
|
|
5085
|
+
* policy is installed after the same validation genesis applies, so it
|
|
5086
|
+
* cannot be born locked out;
|
|
5087
|
+
* - both carry a policy: they must agree. A duplicate preserves its source's
|
|
5088
|
+
* policy (see {@link assertAuthPreservedOnDuplicate}), and anything else is
|
|
5089
|
+
* an attempt to replace one policy with another.
|
|
5090
|
+
*/
|
|
5091
|
+
function resolveSnapshotAuth(documentId, documentType, current, incoming) {
|
|
5092
|
+
const currentAuth = current ?? createAuthState({
|
|
5093
|
+
version: 0,
|
|
5094
|
+
grants: []
|
|
5095
|
+
});
|
|
5096
|
+
if (!incoming || !incoming.version) return currentAuth;
|
|
5097
|
+
if (currentAuth.version !== 0) {
|
|
5098
|
+
if (stringify$1(incoming) !== stringify$1(currentAuth)) throw new AuthPolicyNotPreservedError(documentId);
|
|
5099
|
+
return incoming;
|
|
5100
|
+
}
|
|
5101
|
+
if (!Array.isArray(incoming.grants)) throw new InvalidActionInputError({ grants: "must be an array" });
|
|
5102
|
+
assertValidInitialGrants(incoming.grants, documentType, incoming.creator);
|
|
5103
|
+
return incoming;
|
|
5104
|
+
}
|
|
4934
5105
|
/** UNDO, REDO and PRUNE are rejected on the auth scope. */
|
|
4935
5106
|
function assertAuthScopeActionAllowed(action) {
|
|
4936
5107
|
if (action.scope === "auth" && [
|
|
@@ -4939,6 +5110,12 @@ function assertAuthScopeActionAllowed(action) {
|
|
|
4939
5110
|
"PRUNE"
|
|
4940
5111
|
].includes(action.type)) throw new AuthActionNotAllowedError(action.type);
|
|
4941
5112
|
}
|
|
5113
|
+
/**
|
|
5114
|
+
* True iff authorization rejected the action.
|
|
5115
|
+
*/
|
|
5116
|
+
function isDenied(operation) {
|
|
5117
|
+
return operation.deniedReason !== void 0;
|
|
5118
|
+
}
|
|
4942
5119
|
const BaseDocumentHeaderSchema = object({
|
|
4943
5120
|
id: string(),
|
|
4944
5121
|
name: string(),
|
|
@@ -5121,6 +5298,22 @@ function garbageCollectV2(sortedOperations) {
|
|
|
5121
5298
|
const defaultCreateState = (state) => {
|
|
5122
5299
|
return state;
|
|
5123
5300
|
};
|
|
5301
|
+
/**
|
|
5302
|
+
* Records an operation in the history without applying it, which is what a
|
|
5303
|
+
* denied operation needs: it occupies its index and contributes no state.
|
|
5304
|
+
*
|
|
5305
|
+
* The scope defaults to the action's own, and is passed explicitly by a rebuild
|
|
5306
|
+
* that is walking one stream and does not want to trust the action's copy.
|
|
5307
|
+
*/
|
|
5308
|
+
function appendWithoutApplying(document, operation, scope = operation.action.scope) {
|
|
5309
|
+
return {
|
|
5310
|
+
...document,
|
|
5311
|
+
operations: {
|
|
5312
|
+
...document.operations,
|
|
5313
|
+
[scope]: [...document.operations[scope] ?? [], operation]
|
|
5314
|
+
}
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5124
5317
|
function replayDocument(initialState, operations, reducer, header, dispatch, skipHeaderOperations = {}, options) {
|
|
5125
5318
|
const { checkHashes = true, reuseOperationResultingState, operationResultingStateParser = parseResultingState, skipIndexValidation } = options || {};
|
|
5126
5319
|
const backfilledInitialState = backfillAuthState(initialState);
|
|
@@ -5165,6 +5358,7 @@ function replayDocument(initialState, operations, reducer, header, dispatch, ski
|
|
|
5165
5358
|
};
|
|
5166
5359
|
let result = document;
|
|
5167
5360
|
if (operationsToReplay.length) result = operationsToReplay.reduce((document, operation) => {
|
|
5361
|
+
if (isDenied(operation)) return appendWithoutApplying(document, operation);
|
|
5168
5362
|
return reducer(document, operation.action, dispatch, {
|
|
5169
5363
|
ignoreSkipOperations: true,
|
|
5170
5364
|
checkHashes,
|
|
@@ -5446,13 +5640,15 @@ function redoOperation(document, action, skip) {
|
|
|
5446
5640
|
});
|
|
5447
5641
|
}
|
|
5448
5642
|
function loadStateOperation(document, action) {
|
|
5643
|
+
const loaded = backfillAuthState(action.state.data);
|
|
5644
|
+
loaded.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, loaded.auth);
|
|
5449
5645
|
return {
|
|
5450
5646
|
...document,
|
|
5451
5647
|
header: {
|
|
5452
5648
|
...document.header,
|
|
5453
5649
|
name: action.state.name
|
|
5454
5650
|
},
|
|
5455
|
-
state:
|
|
5651
|
+
state: loaded
|
|
5456
5652
|
};
|
|
5457
5653
|
}
|
|
5458
5654
|
function replayOperations(initialState, clearedOperations, stateReducer, header, dispatch, documentReducer = baseReducer, skipHeaderOperations = {}, options) {
|
|
@@ -6474,10 +6670,12 @@ function applyInitialState(document, action) {
|
|
|
6474
6670
|
const input = action.input;
|
|
6475
6671
|
const newState = input.initialState || input.state;
|
|
6476
6672
|
if (newState) {
|
|
6477
|
-
|
|
6673
|
+
const merged = backfillAuthState({
|
|
6478
6674
|
...document.state,
|
|
6479
6675
|
...newState
|
|
6480
6676
|
});
|
|
6677
|
+
merged.auth = resolveSnapshotAuth(document.header.id, document.header.documentType, backfillAuthState({ ...document.state }).auth, merged.auth);
|
|
6678
|
+
document.state = merged;
|
|
6481
6679
|
document.initialState = document.state;
|
|
6482
6680
|
}
|
|
6483
6681
|
}
|
|
@@ -6655,7 +6853,8 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6655
6853
|
const segEnd = k < validatedUpgrades.length ? boundaries[k]?.[s] ?? ops.length : ops.length;
|
|
6656
6854
|
const segOps = ops.slice(segStart, segEnd);
|
|
6657
6855
|
for (const op of segOps) {
|
|
6658
|
-
document =
|
|
6856
|
+
if (isDenied(op)) document = appendWithoutApplying(document, op, s);
|
|
6857
|
+
else document = reducer(document, op.action, dispatch, {
|
|
6659
6858
|
ignoreSkipOperations: true,
|
|
6660
6859
|
checkHashes,
|
|
6661
6860
|
skipIndexValidation,
|
|
@@ -6672,6 +6871,7 @@ function replayDocumentVersioned(initialState, operations, config, header, dispa
|
|
|
6672
6871
|
if (!spineOp) continue;
|
|
6673
6872
|
const spineActionType = spineOp.action.type;
|
|
6674
6873
|
if (spineActionType === "CREATE_DOCUMENT" || spineActionType === "UPGRADE_DOCUMENT") continue;
|
|
6874
|
+
if (isDenied(spineOp)) continue;
|
|
6675
6875
|
if (spineActionType === "DELETE_DOCUMENT") document = applyDeleteDocumentAction(document, spineOp.action);
|
|
6676
6876
|
else document = reducer(document, spineOp.action, dispatch, {
|
|
6677
6877
|
ignoreSkipOperations: true,
|
|
@@ -7925,4 +8125,4 @@ const driveDocumentModelModule = {
|
|
|
7925
8125
|
//#endregion
|
|
7926
8126
|
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 };
|
|
7927
8127
|
|
|
7928
|
-
//# sourceMappingURL=document-drive-
|
|
8128
|
+
//# sourceMappingURL=document-drive-CI0J7nMj.mjs.map
|