@owlmeans/server-planning 0.1.18-rc.21 → 0.1.18-rc.22
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/README.md +24 -17
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-planning/SKILL.md +28 -28
- package/build/actions/apply-schema-request.d.ts +8 -0
- package/build/actions/apply-schema-request.d.ts.map +1 -0
- package/build/actions/apply-schema-request.js +31 -0
- package/build/actions/apply-schema-request.js.map +1 -0
- package/build/actions/commit.d.ts +3 -3
- package/build/actions/commit.d.ts.map +1 -1
- package/build/actions/commit.js +5 -4
- package/build/actions/commit.js.map +1 -1
- package/build/actions/define-schemas.d.ts +13 -0
- package/build/actions/define-schemas.d.ts.map +1 -0
- package/build/actions/define-schemas.js +28 -0
- package/build/actions/define-schemas.js.map +1 -0
- package/build/actions/execute.d.ts +8 -28
- package/build/actions/execute.d.ts.map +1 -1
- package/build/actions/execute.js +17 -101
- package/build/actions/execute.js.map +1 -1
- package/build/actions/execution/types.d.ts +34 -0
- package/build/actions/execution/types.d.ts.map +1 -0
- package/build/actions/execution/types.js +2 -0
- package/build/actions/execution/types.js.map +1 -0
- package/build/actions/execution.d.ts +4 -0
- package/build/actions/execution.d.ts.map +1 -0
- package/build/actions/execution.js +79 -0
- package/build/actions/execution.js.map +1 -0
- package/build/actions/get-card.d.ts +6 -0
- package/build/actions/get-card.d.ts.map +1 -0
- package/build/actions/get-card.js +9 -0
- package/build/actions/get-card.js.map +1 -0
- package/build/actions/get-specification.d.ts +6 -0
- package/build/actions/get-specification.d.ts.map +1 -0
- package/build/actions/get-specification.js +9 -0
- package/build/actions/get-specification.js.map +1 -0
- package/build/actions/index.d.ts +12 -3
- package/build/actions/index.d.ts.map +1 -1
- package/build/actions/index.js +11 -3
- package/build/actions/index.js.map +1 -1
- package/build/actions/links.d.ts +3 -3
- package/build/actions/links.d.ts.map +1 -1
- package/build/actions/links.js +6 -5
- package/build/actions/links.js.map +1 -1
- package/build/actions/list-card-specifications.d.ts +6 -0
- package/build/actions/list-card-specifications.d.ts.map +1 -0
- package/build/actions/list-card-specifications.js +11 -0
- package/build/actions/list-card-specifications.js.map +1 -0
- package/build/actions/list-card-transitions.d.ts +6 -0
- package/build/actions/list-card-transitions.d.ts.map +1 -0
- package/build/actions/list-card-transitions.js +11 -0
- package/build/actions/list-card-transitions.js.map +1 -0
- package/build/actions/list-cards.d.ts +6 -0
- package/build/actions/list-cards.d.ts.map +1 -0
- package/build/actions/list-cards.js +10 -0
- package/build/actions/list-cards.js.map +1 -0
- package/build/actions/list-schemas.d.ts +13 -0
- package/build/actions/list-schemas.d.ts.map +1 -0
- package/build/actions/list-schemas.js +20 -0
- package/build/actions/list-schemas.js.map +1 -0
- package/build/actions/{specs.d.ts → list-specification-revisions.d.ts} +1 -3
- package/build/actions/list-specification-revisions.d.ts.map +1 -0
- package/build/actions/list-specification-revisions.js +10 -0
- package/build/actions/list-specification-revisions.js.map +1 -0
- package/build/actions/summarize-cards.d.ts +6 -0
- package/build/actions/summarize-cards.d.ts.map +1 -0
- package/build/actions/summarize-cards.js +11 -0
- package/build/actions/summarize-cards.js.map +1 -0
- package/build/actions/transitions.d.ts +3 -3
- package/build/actions/transitions.d.ts.map +1 -1
- package/build/actions/transitions.js +4 -3
- package/build/actions/transitions.js.map +1 -1
- package/build/actions/types.d.ts +5 -3
- package/build/actions/types.d.ts.map +1 -1
- package/build/actions/watch.d.ts +2 -2
- package/build/actions/watch.d.ts.map +1 -1
- package/build/actions/watch.js +2 -2
- package/build/actions/watch.js.map +1 -1
- package/build/conformance/assert/types.d.ts +19 -0
- package/build/conformance/assert/types.d.ts.map +1 -0
- package/build/conformance/assert/types.js +2 -0
- package/build/conformance/assert/types.js.map +1 -0
- package/build/conformance/assert.d.ts +8 -13
- package/build/conformance/assert.d.ts.map +1 -1
- package/build/conformance/assert.js +41 -43
- package/build/conformance/assert.js.map +1 -1
- package/build/conformance/cases.d.ts.map +1 -1
- package/build/conformance/cases.js +86 -67
- package/build/conformance/cases.js.map +1 -1
- package/build/conformance/clock.d.ts +6 -0
- package/build/conformance/clock.d.ts.map +1 -0
- package/build/conformance/clock.js +12 -0
- package/build/conformance/clock.js.map +1 -0
- package/build/conformance/consts.d.ts +3 -1
- package/build/conformance/consts.d.ts.map +1 -1
- package/build/conformance/consts.js +84 -1
- package/build/conformance/consts.js.map +1 -1
- package/build/conformance/errors.d.ts +5 -0
- package/build/conformance/errors.d.ts.map +1 -0
- package/build/conformance/errors.js +8 -0
- package/build/conformance/errors.js.map +1 -0
- package/build/conformance/fixtures/types.d.ts +13 -0
- package/build/conformance/fixtures/types.d.ts.map +1 -0
- package/build/conformance/fixtures/types.js +2 -0
- package/build/conformance/fixtures/types.js.map +1 -0
- package/build/conformance/fixtures.d.ts +8 -8
- package/build/conformance/fixtures.d.ts.map +1 -1
- package/build/conformance/fixtures.js +24 -107
- package/build/conformance/fixtures.js.map +1 -1
- package/build/conformance/index.d.ts +3 -0
- package/build/conformance/index.d.ts.map +1 -1
- package/build/conformance/index.js +1 -0
- package/build/conformance/index.js.map +1 -1
- package/build/definitions.d.ts.map +1 -1
- package/build/definitions.js +9 -9
- package/build/definitions.js.map +1 -1
- package/build/executor/changes/types.d.ts +36 -0
- package/build/executor/changes/types.d.ts.map +1 -0
- package/build/executor/changes/types.js +2 -0
- package/build/executor/changes/types.js.map +1 -0
- package/build/executor/changes.d.ts +3 -30
- package/build/executor/changes.d.ts.map +1 -1
- package/build/executor/changes.js +42 -51
- package/build/executor/changes.js.map +1 -1
- package/build/executor/code/types.d.ts +17 -0
- package/build/executor/code/types.d.ts.map +1 -0
- package/build/executor/code/types.js +2 -0
- package/build/executor/code/types.js.map +1 -0
- package/build/executor/code.d.ts +3 -14
- package/build/executor/code.d.ts.map +1 -1
- package/build/executor/code.js +50 -54
- package/build/executor/code.js.map +1 -1
- package/build/executor/creator/types.d.ts +33 -0
- package/build/executor/creator/types.d.ts.map +1 -0
- package/build/executor/creator/types.js +2 -0
- package/build/executor/creator/types.js.map +1 -0
- package/build/executor/creator.d.ts +6 -25
- package/build/executor/creator.d.ts.map +1 -1
- package/build/executor/creator.js +26 -41
- package/build/executor/creator.js.map +1 -1
- package/build/executor/resolve/types.d.ts +30 -0
- package/build/executor/resolve/types.d.ts.map +1 -0
- package/build/executor/resolve/types.js +2 -0
- package/build/executor/resolve/types.js.map +1 -0
- package/build/executor/resolve.d.ts +4 -41
- package/build/executor/resolve.d.ts.map +1 -1
- package/build/executor/resolve.js +142 -157
- package/build/executor/resolve.js.map +1 -1
- package/build/executor/types.d.ts +0 -2
- package/build/executor/types.d.ts.map +1 -1
- package/build/executor/validate.d.ts +1 -1
- package/build/executor/validate.d.ts.map +1 -1
- package/build/executor/validate.js +16 -15
- package/build/executor/validate.js.map +1 -1
- package/build/executor.d.ts +4 -3
- package/build/executor.d.ts.map +1 -1
- package/build/executor.js +18 -17
- package/build/executor.js.map +1 -1
- package/build/facade.d.ts.map +1 -1
- package/build/facade.js +16 -16
- package/build/facade.js.map +1 -1
- package/build/helper.d.ts +1 -6
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +3 -8
- package/build/helper.js.map +1 -1
- package/build/projection.d.ts +2 -0
- package/build/projection.d.ts.map +1 -1
- package/build/projection.js +6 -4
- package/build/projection.js.map +1 -1
- package/build/queue/declare.d.ts +5 -0
- package/build/queue/declare.d.ts.map +1 -0
- package/build/queue/declare.js +5 -0
- package/build/queue/declare.js.map +1 -0
- package/build/queue/index.d.ts +1 -4
- package/build/queue/index.d.ts.map +1 -1
- package/build/queue/index.js +1 -4
- package/build/queue/index.js.map +1 -1
- package/build/store/composite.d.ts.map +1 -1
- package/build/store/composite.js +2 -2
- package/build/store/composite.js.map +1 -1
- package/build/store/fold/types.d.ts +43 -0
- package/build/store/fold/types.d.ts.map +1 -0
- package/build/store/fold/types.js +2 -0
- package/build/store/fold/types.js.map +1 -0
- package/build/store/fold.d.ts +7 -30
- package/build/store/fold.d.ts.map +1 -1
- package/build/store/fold.js +185 -203
- package/build/store/fold.js.map +1 -1
- package/build/store/index.d.ts +1 -0
- package/build/store/index.d.ts.map +1 -1
- package/build/store/index.js.map +1 -1
- package/build/store/memory.d.ts.map +1 -1
- package/build/store/memory.js +0 -0
- package/build/store/memory.js.map +1 -1
- package/build/store/types.local.d.ts +3 -1
- package/build/store/types.local.d.ts.map +1 -1
- package/build/types.d.ts +2 -1
- package/build/types.d.ts.map +1 -1
- package/build/utils/access/types.d.ts +30 -0
- package/build/utils/access/types.d.ts.map +1 -0
- package/build/utils/access/types.js +2 -0
- package/build/utils/access/types.js.map +1 -0
- package/build/utils/access.d.ts +4 -0
- package/build/utils/access.d.ts.map +1 -0
- package/build/utils/access.js +28 -0
- package/build/utils/access.js.map +1 -0
- package/build/utils/guard/types.d.ts +21 -0
- package/build/utils/guard/types.d.ts.map +1 -0
- package/build/utils/guard/types.js +2 -0
- package/build/utils/guard/types.js.map +1 -0
- package/build/utils/guard.d.ts +7 -10
- package/build/utils/guard.d.ts.map +1 -1
- package/build/utils/guard.js +33 -31
- package/build/utils/guard.js.map +1 -1
- package/build/utils/handler/types.d.ts +26 -0
- package/build/utils/handler/types.d.ts.map +1 -0
- package/build/utils/handler/types.js +2 -0
- package/build/utils/handler/types.js.map +1 -0
- package/build/utils/handler.d.ts +6 -0
- package/build/utils/handler.d.ts.map +1 -0
- package/build/utils/handler.js +21 -0
- package/build/utils/handler.js.map +1 -0
- package/build/utils/index.d.ts +8 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +3 -0
- package/build/utils/index.js.map +1 -1
- package/build/utils/request/types.d.ts +23 -0
- package/build/utils/request/types.d.ts.map +1 -0
- package/build/utils/request/types.js +2 -0
- package/build/utils/request/types.js.map +1 -0
- package/build/utils/request.d.ts +4 -0
- package/build/utils/request.d.ts.map +1 -0
- package/build/utils/request.js +27 -0
- package/build/utils/request.js.map +1 -0
- package/build/utils/scope.d.ts +10 -43
- package/build/utils/scope.d.ts.map +1 -1
- package/build/utils/scope.js +21 -99
- package/build/utils/scope.js.map +1 -1
- package/package.json +18 -18
- package/src/actions/apply-schema-request.ts +35 -0
- package/src/actions/commit.ts +7 -5
- package/src/actions/define-schemas.ts +34 -0
- package/src/actions/execute.ts +30 -115
- package/src/actions/execution/types.ts +34 -0
- package/src/actions/execution.ts +96 -0
- package/src/actions/get-card.ts +14 -0
- package/src/actions/get-specification.ts +14 -0
- package/src/actions/index.ts +13 -3
- package/src/actions/links.ts +8 -6
- package/src/actions/list-card-specifications.ts +15 -0
- package/src/actions/list-card-transitions.ts +15 -0
- package/src/actions/list-cards.ts +14 -0
- package/src/actions/list-schemas.ts +29 -0
- package/src/actions/{specs.ts → list-specification-revisions.ts} +4 -11
- package/src/actions/summarize-cards.ts +15 -0
- package/src/actions/transitions.ts +6 -4
- package/src/actions/types.ts +4 -3
- package/src/actions/watch.ts +4 -3
- package/src/conformance/assert/types.ts +16 -0
- package/src/conformance/assert.ts +49 -41
- package/src/conformance/cases.ts +88 -67
- package/src/conformance/clock.ts +11 -0
- package/src/conformance/consts.ts +87 -1
- package/src/conformance/errors.ts +7 -0
- package/src/conformance/fixtures/types.ts +11 -0
- package/src/conformance/fixtures.ts +32 -107
- package/src/conformance/index.ts +3 -0
- package/src/definitions.ts +9 -9
- package/src/executor/changes/types.ts +38 -0
- package/src/executor/changes.ts +48 -63
- package/src/executor/code/types.ts +23 -0
- package/src/executor/code.ts +60 -61
- package/src/executor/creator/types.ts +33 -0
- package/src/executor/creator.ts +33 -41
- package/src/executor/resolve/types.ts +30 -0
- package/src/executor/resolve.ts +153 -167
- package/src/executor/types.ts +0 -3
- package/src/executor/validate.ts +17 -16
- package/src/executor.ts +20 -17
- package/src/facade.ts +16 -16
- package/src/helper.ts +3 -8
- package/src/projection.ts +8 -4
- package/src/queue/declare.ts +7 -0
- package/src/queue/index.ts +1 -8
- package/src/store/composite.ts +2 -2
- package/src/store/fold/types.ts +44 -0
- package/src/store/fold.ts +209 -212
- package/src/store/index.ts +1 -0
- package/src/store/memory.ts +0 -0
- package/src/store/types.local.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils/access/types.ts +30 -0
- package/src/utils/access.ts +33 -0
- package/src/utils/guard/types.ts +19 -0
- package/src/utils/guard.ts +41 -30
- package/src/utils/handler/types.ts +28 -0
- package/src/utils/handler.ts +35 -0
- package/src/utils/index.ts +9 -1
- package/src/utils/request/types.ts +23 -0
- package/src/utils/request.ts +40 -0
- package/src/utils/scope.ts +25 -108
- package/tests/creator.spec.ts +18 -18
- package/build/actions/cards.d.ts +0 -14
- package/build/actions/cards.d.ts.map +0 -1
- package/build/actions/cards.js +0 -32
- package/build/actions/cards.js.map +0 -1
- package/build/actions/schemas.d.ts +0 -28
- package/build/actions/schemas.d.ts.map +0 -1
- package/build/actions/schemas.js +0 -69
- package/build/actions/schemas.js.map +0 -1
- package/build/actions/specs.d.ts.map +0 -1
- package/build/actions/specs.js +0 -14
- package/build/actions/specs.js.map +0 -1
- package/src/actions/cards.ts +0 -48
- package/src/actions/schemas.ts +0 -87
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PlanningScope, TransitionActor } from '@owlmeans/planning';
|
|
2
|
+
import type { PlanningAccess } from '../../types.js';
|
|
3
|
+
/** One request's identity as planning reads it — built at the top of a handler, never stored. */
|
|
4
|
+
export interface RequestScope {
|
|
5
|
+
/** The authenticated subject of a request, as a transition names it. */
|
|
6
|
+
actorOf: () => TransitionActor;
|
|
7
|
+
/**
|
|
8
|
+
* The scope a request reads and writes as.
|
|
9
|
+
*
|
|
10
|
+
* `entityId` is `requireEntityKey(req)` — the resolved organization id, never a value from the
|
|
11
|
+
* body or the query — and `extra` cannot replace it; `extra` adds what the deployment derives
|
|
12
|
+
* (a `channel`, a `service`). The actor is the authenticated subject plus that channel.
|
|
13
|
+
*
|
|
14
|
+
* @throws {AuthorizationError} when the request carries no organization
|
|
15
|
+
*/
|
|
16
|
+
scopeOf: (extra?: Partial<PlanningScope>) => PlanningScope;
|
|
17
|
+
/**
|
|
18
|
+
* The scope of a request under a resolved {@link PlanningAccess}: the organization is the
|
|
19
|
+
* resolver's — never the token's, never `extra`'s — and `projects` narrows it.
|
|
20
|
+
*/
|
|
21
|
+
accessScopeOf: (access: PlanningAccess, extra?: Partial<PlanningScope>) => PlanningScope;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/request/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,OAAO,EAAE,MAAM,eAAe,CAAA;IAC9B;;;;;;;;OAQG;IACH,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,aAAa,CAAA;IAC1D;;;OAGG;IACH,aAAa,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,aAAa,CAAA;CACzF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/request/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/utils/request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAG3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAMtD,eAAO,MAAM,gBAAgB,QAAS,eAAe,KAAG,YA6BvD,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { makeEntityScope } from '@owlmeans/auth-common';
|
|
2
|
+
const clean = (record) => Object.fromEntries(Object.entries(record).filter(([, value]) => value != null && value !== ''));
|
|
3
|
+
export const makeRequestScope = (req) => {
|
|
4
|
+
const actorOf = () => clean({
|
|
5
|
+
profileId: req.auth?.profileId,
|
|
6
|
+
userId: req.auth?.userId,
|
|
7
|
+
});
|
|
8
|
+
const scopeWith = (entityId, extra) => {
|
|
9
|
+
const subject = actorOf();
|
|
10
|
+
const channel = extra?.channel ?? extra?.actor?.channel;
|
|
11
|
+
return clean({
|
|
12
|
+
...extra,
|
|
13
|
+
...subject,
|
|
14
|
+
entityId,
|
|
15
|
+
channel,
|
|
16
|
+
actor: clean({ ...extra?.actor, ...subject, channel }),
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const scopeOf = (extra) => scopeWith(makeEntityScope(req).requireEntityKey(), extra);
|
|
20
|
+
const accessScopeOf = (access, extra) => {
|
|
21
|
+
const { projects: _projects, entityId: _entityId, ...rest } = extra ?? {};
|
|
22
|
+
const scope = scopeWith(access.entityId, rest);
|
|
23
|
+
return access.projects != null ? { ...scope, projects: [...access.projects] } : scope;
|
|
24
|
+
};
|
|
25
|
+
return { actorOf, scopeOf, accessScopeOf };
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/utils/request.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,MAAM,KAAK,GAAG,CAAmB,MAAS,EAAK,EAAE,CAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC,CAAM,CAAA;AAEtG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAoB,EAAgB,EAAE;IACrE,MAAM,OAAO,GAAG,GAAoB,EAAE,CAAC,KAAK,CAAC;QAC3C,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS;QAC9B,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM;KACzB,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG,CAAC,QAAgB,EAAE,KAA8B,EAAiB,EAAE;QACpF,MAAM,OAAO,GAAG,OAAO,EAAE,CAAA;QACzB,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,KAAK,EAAE,OAAO,CAAA;QAEvD,OAAO,KAAK,CAAC;YACX,GAAG,KAAK;YACR,GAAG,OAAO;YACV,QAAQ;YACR,OAAO;YACP,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;SACvD,CAAkB,CAAA;IACrB,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,CAAC,KAA8B,EAAiB,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,EAAE,KAAK,CAAC,CAAA;IAE5H,MAAM,aAAa,GAAG,CAAC,MAAsB,EAAE,KAA8B,EAAiB,EAAE;QAC9F,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAA;QACzE,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAE9C,OAAO,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACvF,CAAC,CAAA;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAA;AAC5C,CAAC,CAAA"}
|
package/build/utils/scope.d.ts
CHANGED
|
@@ -1,57 +1,24 @@
|
|
|
1
1
|
import type { BasicConfig, BasicContext } from '@owlmeans/context';
|
|
2
2
|
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
3
|
-
import {
|
|
3
|
+
import type { PlanningFacade, PlanningScope, PlanningService, TransitionActor, Workcard } from '@owlmeans/planning';
|
|
4
4
|
import type { PlanningAccess, PlanningAccessGrants, PlanningHandlerOptions } from '../types.js';
|
|
5
5
|
import type { HandlerScope } from './types.js';
|
|
6
|
-
/**
|
|
6
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).actorOf()` */
|
|
7
7
|
export declare const actorOf: (req: AbstractRequest) => TransitionActor;
|
|
8
|
-
/**
|
|
9
|
-
* The scope a request reads and writes as.
|
|
10
|
-
*
|
|
11
|
-
* `entityId` is `requireEntityKey(req)` — the resolved organization id, never a value from the
|
|
12
|
-
* body or the query — and `extra` cannot replace it; `extra` adds what the deployment derives
|
|
13
|
-
* (a `channel`, a `service`). The actor is the authenticated subject plus that channel.
|
|
14
|
-
*
|
|
15
|
-
* @throws {AuthorizationError} when the request carries no organization
|
|
16
|
-
*/
|
|
8
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).scopeOf(…)` */
|
|
17
9
|
export declare const scopeOf: (req: AbstractRequest, extra?: Partial<PlanningScope>) => PlanningScope;
|
|
18
|
-
/**
|
|
19
|
-
* The scope of a request under a resolved {@link PlanningAccess}: the organization is the
|
|
20
|
-
* resolver's — never the token's, never `extra`'s — and `projects` narrows it.
|
|
21
|
-
*/
|
|
10
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).accessScopeOf(…)` */
|
|
22
11
|
export declare const accessScopeOf: (req: AbstractRequest, access: PlanningAccess, extra?: Partial<PlanningScope>) => PlanningScope;
|
|
12
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).planningServiceOf(…)` */
|
|
23
13
|
export declare const planningServiceOf: (ctx: BasicContext<BasicConfig>, opts?: Pick<PlanningHandlerOptions, 'service'>) => PlanningService;
|
|
24
|
-
/**
|
|
25
|
-
* The facade a handler works through, and the access it was resolved under.
|
|
26
|
-
*
|
|
27
|
-
* Without `opts.access` it is exactly the request's scope plus what `opts.scope` derives. With it,
|
|
28
|
-
* the resolver names the organization and the visible projects; a throw from the resolver is the
|
|
29
|
-
* request's error.
|
|
30
|
-
*/
|
|
14
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).handlerScopeOf(…)` */
|
|
31
15
|
export declare const handlerScopeOf: (ctx: BasicContext<BasicConfig>, req: AbstractRequest, opts?: PlanningHandlerOptions) => Promise<HandlerScope>;
|
|
32
|
-
/**
|
|
16
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).handlerFacade(…)` */
|
|
33
17
|
export declare const handlerFacade: (ctx: BasicContext<BasicConfig>, req: AbstractRequest, opts?: PlanningHandlerOptions) => Promise<PlanningFacade>;
|
|
34
|
-
/**
|
|
35
|
-
* Refuse a write the access does not grant. No access, or access without `grants`, gates nothing;
|
|
36
|
-
* a `grants` object refuses every flag it leaves out. `true` grants everything; a list grants the
|
|
37
|
-
* project ids it names — `target` is the project the write is about (`undefined` for the
|
|
38
|
-
* organization's root, which only `true` reaches).
|
|
39
|
-
*
|
|
40
|
-
* @throws {PlanningForbidden}
|
|
41
|
-
*/
|
|
18
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).assertGranted(…)` */
|
|
42
19
|
export declare const assertGranted: (access: PlanningAccess | undefined, grant: keyof PlanningAccessGrants, target?: string) => void;
|
|
43
|
-
/**
|
|
44
|
-
* A card the access's `writes` admits — the rule a narrowed read admits, over `writes`: a project
|
|
45
|
-
* it names, or a card whose `parents` name one. A specification is admitted through its parent card
|
|
46
|
-
* by the caller. No `writes` admits everything.
|
|
47
|
-
*/
|
|
20
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).writableIn(…)` */
|
|
48
21
|
export declare const writableIn: (access: PlanningAccess | undefined, card: Pick<Workcard, 'id' | 'parents'>) => boolean;
|
|
49
|
-
/**
|
|
50
|
-
* Refuse a write into a project the access's `writes` leaves out. No `writes` refuses nothing;
|
|
51
|
-
* `target` is the project the write is in (`undefined` for the organization's root, which a set
|
|
52
|
-
* `writes` never admits).
|
|
53
|
-
*
|
|
54
|
-
* @throws {PlanningForbidden}
|
|
55
|
-
*/
|
|
22
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).assertWrites(…)` */
|
|
56
23
|
export declare const assertWrites: (access: PlanningAccess | undefined, target?: string) => void;
|
|
57
24
|
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AACnH,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAI/F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,kFAAkF;AAClF,eAAO,MAAM,OAAO,QAAS,eAAe,KAAG,eAAkD,CAAA;AAEjG,mFAAmF;AACnF,eAAO,MAAM,OAAO,QAAS,eAAe,UAAU,OAAO,CAAC,aAAa,CAAC,KAAG,aACzC,CAAA;AAEtC,yFAAyF;AACzF,eAAO,MAAM,aAAa,QACnB,eAAe,UAAU,cAAc,UAAU,OAAO,CAAC,aAAa,CAAC,KAC3E,aAAmE,CAAA;AAEtE,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,QACvB,YAAY,CAAC,WAAW,CAAC,SAAS,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAC,KAC7E,eAAiE,CAAA;AAEpE,2FAA2F;AAC3F,eAAO,MAAM,cAAc,QACpB,YAAY,CAAC,WAAW,CAAC,OAAO,eAAe,SAAS,sBAAsB,KAClF,OAAO,CAAC,YAAY,CAA2D,CAAA;AAElF,0FAA0F;AAC1F,eAAO,MAAM,aAAa,QACnB,YAAY,CAAC,WAAW,CAAC,OAAO,eAAe,SAAS,sBAAsB,KAClF,OAAO,CAAC,cAAc,CAA0D,CAAA;AAEnF,mGAAmG;AACnG,eAAO,MAAM,aAAa,WAChB,cAAc,GAAG,SAAS,SAAS,MAAM,oBAAoB,WAAW,MAAM,KACrF,IAAoE,CAAA;AAEvE,gGAAgG;AAChG,eAAO,MAAM,UAAU,WAAY,cAAc,GAAG,SAAS,QAAQ,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC,KAAG,OACtD,CAAA;AAElD,kGAAkG;AAClG,eAAO,MAAM,YAAY,WAAY,cAAc,GAAG,SAAS,WAAW,MAAM,KAAG,IAC7B,CAAA"}
|
package/build/utils/scope.js
CHANGED
|
@@ -1,100 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
export const actorOf = (req) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
* `entityId` is `requireEntityKey(req)` — the resolved organization id, never a value from the
|
|
24
|
-
* body or the query — and `extra` cannot replace it; `extra` adds what the deployment derives
|
|
25
|
-
* (a `channel`, a `service`). The actor is the authenticated subject plus that channel.
|
|
26
|
-
*
|
|
27
|
-
* @throws {AuthorizationError} when the request carries no organization
|
|
28
|
-
*/
|
|
29
|
-
export const scopeOf = (req, extra) => scopeWith(req, requireEntityKey(req), extra);
|
|
30
|
-
/**
|
|
31
|
-
* The scope of a request under a resolved {@link PlanningAccess}: the organization is the
|
|
32
|
-
* resolver's — never the token's, never `extra`'s — and `projects` narrows it.
|
|
33
|
-
*/
|
|
34
|
-
export const accessScopeOf = (req, access, extra) => {
|
|
35
|
-
const { projects: _projects, entityId: _entityId, ...rest } = extra ?? {};
|
|
36
|
-
const scope = scopeWith(req, access.entityId, rest);
|
|
37
|
-
return access.projects != null ? { ...scope, projects: [...access.projects] } : scope;
|
|
38
|
-
};
|
|
39
|
-
export const planningServiceOf = (ctx, opts) => ctx.service(opts?.service ?? PLANNING_SERVICE);
|
|
40
|
-
/**
|
|
41
|
-
* The facade a handler works through, and the access it was resolved under.
|
|
42
|
-
*
|
|
43
|
-
* Without `opts.access` it is exactly the request's scope plus what `opts.scope` derives. With it,
|
|
44
|
-
* the resolver names the organization and the visible projects; a throw from the resolver is the
|
|
45
|
-
* request's error.
|
|
46
|
-
*/
|
|
47
|
-
export const handlerScopeOf = async (ctx, req, opts) => {
|
|
48
|
-
const extra = await opts?.scope?.(req, ctx);
|
|
49
|
-
if (opts?.access == null) {
|
|
50
|
-
return { facade: planningServiceOf(ctx, opts).for(scopeOf(req, extra ?? undefined)) };
|
|
51
|
-
}
|
|
52
|
-
const access = await opts.access(req, ctx);
|
|
53
|
-
return { facade: planningServiceOf(ctx, opts).for(accessScopeOf(req, access, extra ?? undefined)), access };
|
|
54
|
-
};
|
|
55
|
-
/** The facade a handler works through: the request's scope plus what `opts.scope` derives. */
|
|
56
|
-
export const handlerFacade = async (ctx, req, opts) => (await handlerScopeOf(ctx, req, opts)).facade;
|
|
57
|
-
/**
|
|
58
|
-
* Refuse a write the access does not grant. No access, or access without `grants`, gates nothing;
|
|
59
|
-
* a `grants` object refuses every flag it leaves out. `true` grants everything; a list grants the
|
|
60
|
-
* project ids it names — `target` is the project the write is about (`undefined` for the
|
|
61
|
-
* organization's root, which only `true` reaches).
|
|
62
|
-
*
|
|
63
|
-
* @throws {PlanningForbidden}
|
|
64
|
-
*/
|
|
65
|
-
export const assertGranted = (access, grant, target) => {
|
|
66
|
-
if (access?.grants == null) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const granted = access.grants[grant];
|
|
70
|
-
if (granted === true || (Array.isArray(granted) && target != null && granted.includes(target))) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
throw new PlanningForbidden(`${grant}:${target ?? 'root'}`);
|
|
74
|
-
};
|
|
75
|
-
/**
|
|
76
|
-
* A card the access's `writes` admits — the rule a narrowed read admits, over `writes`: a project
|
|
77
|
-
* it names, or a card whose `parents` name one. A specification is admitted through its parent card
|
|
78
|
-
* by the caller. No `writes` admits everything.
|
|
79
|
-
*/
|
|
80
|
-
export const writableIn = (access, card) => {
|
|
81
|
-
const writes = access?.writes;
|
|
82
|
-
if (writes == null) {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
return (card.id != null && writes.includes(card.id)) || card.parents.some(parent => writes.includes(parent));
|
|
86
|
-
};
|
|
87
|
-
/**
|
|
88
|
-
* Refuse a write into a project the access's `writes` leaves out. No `writes` refuses nothing;
|
|
89
|
-
* `target` is the project the write is in (`undefined` for the organization's root, which a set
|
|
90
|
-
* `writes` never admits).
|
|
91
|
-
*
|
|
92
|
-
* @throws {PlanningForbidden}
|
|
93
|
-
*/
|
|
94
|
-
export const assertWrites = (access, target) => {
|
|
95
|
-
if (access?.writes == null || (target != null && access.writes.includes(target))) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
throw new PlanningForbidden(`writes:${target ?? 'root'}`);
|
|
99
|
-
};
|
|
1
|
+
import { makePlanningAccessModel } from './access.js';
|
|
2
|
+
import { planningHandlerOf } from './handler.js';
|
|
3
|
+
import { makeRequestScope } from './request.js';
|
|
4
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).actorOf()` */
|
|
5
|
+
export const actorOf = (req) => makeRequestScope(req).actorOf();
|
|
6
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).scopeOf(…)` */
|
|
7
|
+
export const scopeOf = (req, extra) => makeRequestScope(req).scopeOf(extra);
|
|
8
|
+
/** @deprecated compat:factory-refactor — use `makeRequestScope(req).accessScopeOf(…)` */
|
|
9
|
+
export const accessScopeOf = (req, access, extra) => makeRequestScope(req).accessScopeOf(access, extra);
|
|
10
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).planningServiceOf(…)` */
|
|
11
|
+
export const planningServiceOf = (ctx, opts) => planningHandlerOf(ctx).planningServiceOf(opts);
|
|
12
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).handlerScopeOf(…)` */
|
|
13
|
+
export const handlerScopeOf = async (ctx, req, opts) => await planningHandlerOf(ctx).handlerScopeOf(req, opts);
|
|
14
|
+
/** @deprecated compat:factory-refactor — use `planningHandlerOf(ctx).handlerFacade(…)` */
|
|
15
|
+
export const handlerFacade = async (ctx, req, opts) => await planningHandlerOf(ctx).handlerFacade(req, opts);
|
|
16
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).assertGranted(…)` */
|
|
17
|
+
export const assertGranted = (access, grant, target) => makePlanningAccessModel(access).assertGranted(grant, target);
|
|
18
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).writableIn(…)` */
|
|
19
|
+
export const writableIn = (access, card) => makePlanningAccessModel(access).writableIn(card);
|
|
20
|
+
/** @deprecated compat:factory-refactor — use `makePlanningAccessModel(access).assertWrites(…)` */
|
|
21
|
+
export const assertWrites = (access, target) => makePlanningAccessModel(access).assertWrites(target);
|
|
100
22
|
//# sourceMappingURL=scope.js.map
|
package/build/utils/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/utils/scope.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAG/C,kFAAkF;AAClF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAoB,EAAmB,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAA;AAEjG,mFAAmF;AACnF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAoB,EAAE,KAA8B,EAAiB,EAAE,CAC7F,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAEtC,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,GAAoB,EAAE,MAAsB,EAAE,KAA8B,EAC7D,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAEtE,8FAA8F;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAA8B,EAAE,IAA8C,EAC7D,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAEpE,2FAA2F;AAC3F,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,GAA8B,EAAE,GAAoB,EAAE,IAA6B,EAC5D,EAAE,CAAC,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;AAElF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,GAA8B,EAAE,GAAoB,EAAE,IAA6B,EAC1D,EAAE,CAAC,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;AAEnF,mGAAmG;AACnG,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAkC,EAAE,KAAiC,EAAE,MAAe,EAChF,EAAE,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;AAEvE,gGAAgG;AAChG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAkC,EAAE,IAAsC,EAAW,EAAE,CAChH,uBAAuB,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;AAElD,kGAAkG;AAClG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAkC,EAAE,MAAe,EAAQ,EAAE,CACxF,uBAAuB,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-planning",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.22",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The general planning implementation — the planning service and its plugin/middleware registry, the transition executor, the in-memory store, the protocol handlers and the commit feed.",
|
|
6
6
|
"type": "module",
|
|
@@ -44,22 +44,22 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
48
|
-
"@owlmeans/auth-common": "^0.1.18-rc.
|
|
49
|
-
"@owlmeans/basic-ids": "^0.1.18-rc.
|
|
50
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
51
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
52
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
53
|
-
"@owlmeans/planning": "^0.1.18-rc.
|
|
54
|
-
"@owlmeans/queue": "^0.1.18-rc.
|
|
55
|
-
"@owlmeans/resource": "^0.1.18-rc.
|
|
56
|
-
"@owlmeans/log": "^0.1.18-rc.
|
|
57
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
58
|
-
"@owlmeans/server-api": "^0.1.18-rc.
|
|
59
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
60
|
-
"@owlmeans/server-entrypoint": "^0.1.18-rc.
|
|
61
|
-
"@owlmeans/server-socket": "^0.1.18-rc.
|
|
62
|
-
"@owlmeans/socket": "^0.1.18-rc.
|
|
47
|
+
"@owlmeans/auth": "^0.1.18-rc.40",
|
|
48
|
+
"@owlmeans/auth-common": "^0.1.18-rc.47",
|
|
49
|
+
"@owlmeans/basic-ids": "^0.1.18-rc.37",
|
|
50
|
+
"@owlmeans/context": "^0.1.18-rc.34",
|
|
51
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.41",
|
|
52
|
+
"@owlmeans/error": "^0.1.18-rc.38",
|
|
53
|
+
"@owlmeans/planning": "^0.1.18-rc.19",
|
|
54
|
+
"@owlmeans/queue": "^0.1.18-rc.41",
|
|
55
|
+
"@owlmeans/resource": "^0.1.18-rc.40",
|
|
56
|
+
"@owlmeans/log": "^0.1.18-rc.2",
|
|
57
|
+
"@owlmeans/route": "^0.1.18-rc.35",
|
|
58
|
+
"@owlmeans/server-api": "^0.1.18-rc.51",
|
|
59
|
+
"@owlmeans/server-context": "^0.1.18-rc.43",
|
|
60
|
+
"@owlmeans/server-entrypoint": "^0.1.18-rc.40",
|
|
61
|
+
"@owlmeans/server-socket": "^0.1.18-rc.54",
|
|
62
|
+
"@owlmeans/socket": "^0.1.18-rc.40"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"ajv": "*",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@owlmeans/dep-config": "workspace:*",
|
|
70
|
-
"@owlmeans/test": "^0.1.18-rc.
|
|
70
|
+
"@owlmeans/test": "^0.1.18-rc.35",
|
|
71
71
|
"@types/bun": "^1.4.2",
|
|
72
72
|
"@types/node": "^26.6.4",
|
|
73
73
|
"ajv": "^8.20.0",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SchemaWriteMode, type PlanningDefinitions, type SchemaDefineReply, type SchemaDefineRequest, type ScopedSchemaRecord } from '@owlmeans/planning'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Apply one `schema.define` request to a facade's definitions: the declarations in the request's
|
|
5
|
+
* mode (flows before types), then the retirements — answering what was written and the layer as it
|
|
6
|
+
* resolves afterwards.
|
|
7
|
+
*/
|
|
8
|
+
export const applySchemaRequest = async (
|
|
9
|
+
definitions: PlanningDefinitions, request: SchemaDefineRequest
|
|
10
|
+
): Promise<SchemaDefineReply> => {
|
|
11
|
+
const layer = request.project != null ? { project: request.project } : {}
|
|
12
|
+
const declarations = { types: request.types ?? [], flows: request.flows ?? [] }
|
|
13
|
+
const records: ScopedSchemaRecord[] = []
|
|
14
|
+
|
|
15
|
+
switch (request.mode ?? SchemaWriteMode.Define) {
|
|
16
|
+
case SchemaWriteMode.Put:
|
|
17
|
+
for (const flow of declarations.flows) {
|
|
18
|
+
records.push(await definitions.putFlow(flow, layer))
|
|
19
|
+
}
|
|
20
|
+
for (const type of declarations.types) {
|
|
21
|
+
records.push(await definitions.putType(type, layer))
|
|
22
|
+
}
|
|
23
|
+
break
|
|
24
|
+
case SchemaWriteMode.Seed:
|
|
25
|
+
records.push(...await definitions.seed(declarations, layer))
|
|
26
|
+
break
|
|
27
|
+
default:
|
|
28
|
+
records.push(...await definitions.define(declarations, layer))
|
|
29
|
+
}
|
|
30
|
+
for (const key of request.retire ?? []) {
|
|
31
|
+
records.push(await definitions.retire(key.kind, key.key, layer))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { records, bundle: await definitions.bundle(request.project) }
|
|
35
|
+
}
|
package/src/actions/commit.ts
CHANGED
|
@@ -2,7 +2,9 @@ import { handlers } from '@owlmeans/server-api'
|
|
|
2
2
|
import { CommitState, MAX_COMMIT_POLL } from '@owlmeans/planning'
|
|
3
3
|
import type { CommitStatus, PlanningProtocols } from '@owlmeans/planning'
|
|
4
4
|
import type { Context, PlanningHandlerOptions } from '../types.js'
|
|
5
|
-
import {
|
|
5
|
+
import { guardHelper } from '../utils/guard.js'
|
|
6
|
+
import { planningHandlerOf } from '../utils/handler.js'
|
|
7
|
+
import type { RequestHandler } from './types.js'
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The poll tool: a commit's status, held open up to `wait` seconds (clamped to `maxPoll`).
|
|
@@ -15,13 +17,13 @@ import { clampSeconds, concealed, handlerFacade } from '../utils/index.js'
|
|
|
15
17
|
*/
|
|
16
18
|
export const getCommit = (
|
|
17
19
|
protocol: PlanningProtocols['commit']['get'], opts?: PlanningHandlerOptions
|
|
18
|
-
):
|
|
19
|
-
handlers<Context>().request(protocol, async (req, ctx) => concealed(async (): Promise<CommitStatus> => {
|
|
20
|
-
const facade = await handlerFacade(
|
|
20
|
+
): RequestHandler =>
|
|
21
|
+
handlers<Context>().request(protocol, async (req, ctx) => guardHelper.concealed(async (): Promise<CommitStatus> => {
|
|
22
|
+
const facade = await planningHandlerOf(ctx).handlerFacade(req, opts)
|
|
21
23
|
const transition = `${req.params.transition}`
|
|
22
24
|
|
|
23
25
|
let status = await facade.commits.status(transition)
|
|
24
|
-
const wait = clampSeconds(req.query?.wait, opts?.maxPoll ?? MAX_COMMIT_POLL)
|
|
26
|
+
const wait = guardHelper.clampSeconds(req.query?.wait, opts?.maxPoll ?? MAX_COMMIT_POLL)
|
|
25
27
|
if (status.state !== CommitState.Pending || wait <= 0) {
|
|
26
28
|
return status
|
|
27
29
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { handlers } from '@owlmeans/server-api'
|
|
2
|
+
import { PlanningUnsupported, type PlanningProtocols, type SchemaDefineReply, type SchemaDefineRequest } from '@owlmeans/planning'
|
|
3
|
+
import type { Context, PlanningHandlerOptions } from '../types.js'
|
|
4
|
+
import { makePlanningAccessModel } from '../utils/access.js'
|
|
5
|
+
import { guardHelper } from '../utils/guard.js'
|
|
6
|
+
import { planningHandlerOf } from '../utils/handler.js'
|
|
7
|
+
import { applySchemaRequest } from './apply-schema-request.js'
|
|
8
|
+
import type { RequestHandler } from './types.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The write of data-defined types and flows. A project layer needs the project in the access's
|
|
12
|
+
* `writes` when the resolver answers it; then `grants.defineSchemas` gates when the resolver answers
|
|
13
|
+
* grants (the organization-wide layer needs `true`, a project layer its id).
|
|
14
|
+
*
|
|
15
|
+
* @throws {PlanningUnsupported} where the store holds no data-defined schemas
|
|
16
|
+
* @throws {PlanningForbidden | SchemaConflict | SchemaSealed | SchemaInvalid | SchemaInUse | WorkcardNotFound}
|
|
17
|
+
*/
|
|
18
|
+
export const defineSchemas = (
|
|
19
|
+
protocol: NonNullable<PlanningProtocols['schema']['define']>, opts?: PlanningHandlerOptions
|
|
20
|
+
): RequestHandler =>
|
|
21
|
+
handlers<Context>().request(protocol, async (req, ctx) => guardHelper.concealed(async (): Promise<SchemaDefineReply> => {
|
|
22
|
+
const { facade, access } = await planningHandlerOf(ctx).handlerScopeOf(req, opts)
|
|
23
|
+
const request = (req.body ?? {}) as SchemaDefineRequest
|
|
24
|
+
if (facade.definitions == null) {
|
|
25
|
+
throw new PlanningUnsupported('definitions')
|
|
26
|
+
}
|
|
27
|
+
const model = makePlanningAccessModel(access)
|
|
28
|
+
if (request.project != null) {
|
|
29
|
+
model.assertWrites(request.project)
|
|
30
|
+
}
|
|
31
|
+
model.assertGranted('defineSchemas', request.project)
|
|
32
|
+
|
|
33
|
+
return await applySchemaRequest(facade.definitions, request)
|
|
34
|
+
}))
|
package/src/actions/execute.ts
CHANGED
|
@@ -1,130 +1,45 @@
|
|
|
1
1
|
import { handlers } from '@owlmeans/server-api'
|
|
2
|
-
import {
|
|
3
|
-
DEFAULT_COMMIT_TIMEOUT, isProject, isSpecification, MAX_COMMIT_POLL, normalizeParents, PlanningForbidden,
|
|
4
|
-
TransitionAction, WorkcardKind,
|
|
5
|
-
} from '@owlmeans/planning'
|
|
2
|
+
import { MAX_COMMIT_POLL } from '@owlmeans/planning'
|
|
6
3
|
import type {
|
|
7
4
|
ExecuteOptions, ExecuteRequest, PlanningFacade, PlanningProtocols, PlanningScope, TransitionExecution,
|
|
8
|
-
TransitionReceiptView,
|
|
5
|
+
TransitionReceiptView,
|
|
9
6
|
} from '@owlmeans/planning'
|
|
10
|
-
import { withCreator } from '../executor/creator.js'
|
|
11
7
|
import type { Context, PlanningAccess, PlanningHandlerOptions } from '../types.js'
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* `createdBy` claim is dropped too: the executor's {@link withCreator} stamps the authenticated
|
|
17
|
-
* subject, the same rule an in-process create follows. Applied here as well, so the returned
|
|
18
|
-
* execution already carries it. A `createdBy` in `changes` or `unset` is not dropped: the executor
|
|
19
|
-
* refuses it on every action (`assertCreatorFixed`), so no body moves an owner.
|
|
20
|
-
*/
|
|
21
|
-
export const wireExecution = (body: ExecuteRequest, scope: PlanningScope): TransitionExecution => {
|
|
22
|
-
const { wait: _wait, timeout: _timeout, actor: _actor, ...exec } = body
|
|
23
|
-
if (exec.action === TransitionAction.Create && exec.card != null && typeof exec.card === 'object') {
|
|
24
|
-
const { createdBy: _createdBy, ...draft } = exec.card
|
|
25
|
-
exec.card = draft
|
|
26
|
-
}
|
|
27
|
-
return withCreator(exec, scope)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** `wait`/`timeout` as a server grants them: the timeout never holds a request past `maxPoll`. */
|
|
31
|
-
export const executeOptionsOf = (body: Pick<ExecuteRequest, 'wait' | 'timeout'>, maxPoll: number): ExecuteOptions => {
|
|
32
|
-
const ceiling = maxPoll * 1000
|
|
33
|
-
if (body.wait !== true) {
|
|
34
|
-
return {}
|
|
35
|
-
}
|
|
36
|
-
const asked = Number(body.timeout ?? DEFAULT_COMMIT_TIMEOUT)
|
|
37
|
-
return { wait: true, timeout: Math.min(Number.isFinite(asked) && asked > 0 ? asked : DEFAULT_COMMIT_TIMEOUT, ceiling) }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Refuse an execution outside the access's `writes`: the card it acts on (a specification through
|
|
42
|
-
* its parent card), or every parent a create names, must be one {@link writableIn} admits. A create
|
|
43
|
-
* of a project is `grants.createProjects`' alone. A card or parent this scope cannot see is left to
|
|
44
|
-
* the executor, which answers it as absent.
|
|
45
|
-
*
|
|
46
|
-
* @throws {PlanningForbidden}
|
|
47
|
-
*/
|
|
48
|
-
export const assertExecutionWrites = async (
|
|
49
|
-
facade: PlanningFacade, exec: TransitionExecution, access?: PlanningAccess
|
|
50
|
-
): Promise<void> => {
|
|
51
|
-
if (access?.writes == null) {
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
const admitted = async (card: Workcard): Promise<boolean> => {
|
|
55
|
-
if (writableIn(access, card)) {
|
|
56
|
-
return true
|
|
57
|
-
}
|
|
58
|
-
if (!isSpecification(card) || card.parent == null) {
|
|
59
|
-
return false
|
|
60
|
-
}
|
|
61
|
-
const parent = await facade.cards.load(card.parent)
|
|
62
|
-
return parent == null || writableIn(access, parent)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (exec.action === TransitionAction.Create && exec.card != null && typeof exec.card === 'object') {
|
|
66
|
-
if (exec.card.kind === WorkcardKind.Project) {
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
const parents = normalizeParents(exec.card.parent, exec.card.parents)
|
|
70
|
-
if (parents.length === 0) {
|
|
71
|
-
throw new PlanningForbidden('writes:root')
|
|
72
|
-
}
|
|
73
|
-
for (const id of parents) {
|
|
74
|
-
const parent = await facade.cards.load(id)
|
|
75
|
-
if (parent != null && !await admitted(parent)) {
|
|
76
|
-
throw new PlanningForbidden(`writes:${id}`)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
if (typeof exec.card === 'string' && exec.card !== '') {
|
|
82
|
-
const card = await facade.cards.load(exec.card)
|
|
83
|
-
if (card != null && !await admitted(card)) {
|
|
84
|
-
throw new PlanningForbidden(`writes:${exec.card}`)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* The access a wire execution needs. `writes` first ({@link assertExecutionWrites}); then the
|
|
91
|
-
* grants: `createProjects` for a project create (its primary parent, or the root),
|
|
92
|
-
* `deleteProjects` for the delete of a project card. A card this scope cannot see is left to the
|
|
93
|
-
* executor, which answers it as absent.
|
|
94
|
-
*
|
|
95
|
-
* @throws {PlanningForbidden}
|
|
96
|
-
*/
|
|
97
|
-
export const assertExecutionGranted = async (
|
|
98
|
-
facade: PlanningFacade, exec: TransitionExecution, access?: PlanningAccess
|
|
99
|
-
): Promise<void> => {
|
|
100
|
-
await assertExecutionWrites(facade, exec, access)
|
|
101
|
-
if (access?.grants == null) {
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
if (exec.action === TransitionAction.Create && typeof exec.card === 'object' && exec.card?.kind === WorkcardKind.Project) {
|
|
105
|
-
assertGranted(access, 'createProjects', normalizeParents(exec.card.parent, exec.card.parents)[0])
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
if (exec.action === TransitionAction.Delete && typeof exec.card === 'string') {
|
|
109
|
-
const card = await facade.cards.load(exec.card)
|
|
110
|
-
if (card != null && isProject(card)) {
|
|
111
|
-
assertGranted(access, 'deleteProjects', card.id)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
8
|
+
import { guardHelper } from '../utils/guard.js'
|
|
9
|
+
import { planningHandlerOf } from '../utils/handler.js'
|
|
10
|
+
import { executionHelper } from './execution.js'
|
|
11
|
+
import type { RequestHandler } from './types.js'
|
|
115
12
|
|
|
116
13
|
/** The one write route. */
|
|
117
14
|
export const executePlanning = (
|
|
118
15
|
protocol: PlanningProtocols['execute'], opts?: PlanningHandlerOptions
|
|
119
|
-
):
|
|
120
|
-
handlers<Context>().request(protocol, async (req, ctx) => concealed(async (): Promise<TransitionReceiptView> => {
|
|
121
|
-
const { facade, access } = await handlerScopeOf(
|
|
16
|
+
): RequestHandler =>
|
|
17
|
+
handlers<Context>().request(protocol, async (req, ctx) => guardHelper.concealed(async (): Promise<TransitionReceiptView> => {
|
|
18
|
+
const { facade, access } = await planningHandlerOf(ctx).handlerScopeOf(req, opts)
|
|
122
19
|
const body = (req.body ?? {}) as ExecuteRequest
|
|
123
|
-
const exec = wireExecution(body, facade.scope)
|
|
124
|
-
await assertExecutionGranted(facade, exec, access)
|
|
125
|
-
const receipt = await facade.execute(exec, executeOptionsOf(body, opts?.maxPoll ?? MAX_COMMIT_POLL))
|
|
20
|
+
const exec = executionHelper.wireExecution(body, facade.scope)
|
|
21
|
+
await executionHelper.assertExecutionGranted(facade, exec, access)
|
|
22
|
+
const receipt = await facade.execute(exec, executionHelper.executeOptionsOf(body, opts?.maxPoll ?? MAX_COMMIT_POLL))
|
|
126
23
|
|
|
127
24
|
return receipt.card !== undefined
|
|
128
25
|
? { transition: receipt.transition, card: receipt.card }
|
|
129
26
|
: { transition: receipt.transition }
|
|
130
27
|
}))
|
|
28
|
+
|
|
29
|
+
/** @deprecated compat:factory-refactor — use `executionHelper.wireExecution(…)` */
|
|
30
|
+
export const wireExecution = (body: ExecuteRequest, scope: PlanningScope): TransitionExecution =>
|
|
31
|
+
executionHelper.wireExecution(body, scope)
|
|
32
|
+
|
|
33
|
+
/** @deprecated compat:factory-refactor — use `executionHelper.executeOptionsOf(…)` */
|
|
34
|
+
export const executeOptionsOf = (body: Pick<ExecuteRequest, 'wait' | 'timeout'>, maxPoll: number): ExecuteOptions =>
|
|
35
|
+
executionHelper.executeOptionsOf(body, maxPoll)
|
|
36
|
+
|
|
37
|
+
/** @deprecated compat:factory-refactor — use `executionHelper.assertExecutionWrites(…)` */
|
|
38
|
+
export const assertExecutionWrites = async (
|
|
39
|
+
facade: PlanningFacade, exec: TransitionExecution, access?: PlanningAccess
|
|
40
|
+
): Promise<void> => await executionHelper.assertExecutionWrites(facade, exec, access)
|
|
41
|
+
|
|
42
|
+
/** @deprecated compat:factory-refactor — use `executionHelper.assertExecutionGranted(…)` */
|
|
43
|
+
export const assertExecutionGranted = async (
|
|
44
|
+
facade: PlanningFacade, exec: TransitionExecution, access?: PlanningAccess
|
|
45
|
+
): Promise<void> => await executionHelper.assertExecutionGranted(facade, exec, access)
|