@stigmer/server 3.22.1-dev.20260922095755 → 3.23.0
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/artifactstorage/artifact-storage.d.ts +29 -31
- package/dist/artifactstorage/artifact-storage.d.ts.map +1 -1
- package/dist/artifactstorage/artifact-storage.js +5 -7
- package/dist/artifactstorage/artifact-storage.js.map +1 -1
- package/dist/artifactstorage/r2-storage.d.ts +12 -7
- package/dist/artifactstorage/r2-storage.d.ts.map +1 -1
- package/dist/artifactstorage/r2-storage.js +6 -14
- package/dist/artifactstorage/r2-storage.js.map +1 -1
- package/dist/authorization/authorizer.d.ts +8 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +9 -5
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/derived-tuples.d.ts.map +1 -1
- package/dist/authorization/derived-tuples.js +25 -10
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +8 -7
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +20 -4
- package/dist/authorization/evaluator.js.map +1 -1
- package/dist/authorization/list-read-scope.d.ts.map +1 -1
- package/dist/authorization/list-read-scope.js +9 -5
- package/dist/authorization/list-read-scope.js.map +1 -1
- package/dist/authorization/model/agent.d.ts.map +1 -1
- package/dist/authorization/model/agent.js +5 -4
- package/dist/authorization/model/agent.js.map +1 -1
- package/dist/authorization/model/agent_instance.d.ts.map +1 -1
- package/dist/authorization/model/agent_instance.js +2 -2
- package/dist/authorization/model/agent_instance.js.map +1 -1
- package/dist/authorization/model/mcp_server.d.ts.map +1 -1
- package/dist/authorization/model/mcp_server.js +2 -2
- package/dist/authorization/model/mcp_server.js.map +1 -1
- package/dist/authorization/model/plugin.d.ts.map +1 -1
- package/dist/authorization/model/plugin.js +4 -3
- package/dist/authorization/model/plugin.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +10 -8
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +3 -0
- package/dist/authorization/model/rewrite.js.map +1 -1
- package/dist/authorization/model/skill.d.ts.map +1 -1
- package/dist/authorization/model/skill.js +2 -2
- package/dist/authorization/model/skill.js.map +1 -1
- package/dist/authorization/model/workflow.d.ts.map +1 -1
- package/dist/authorization/model/workflow.js +2 -2
- package/dist/authorization/model/workflow.js.map +1 -1
- package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
- package/dist/authorization/model/workflow_instance.js +2 -2
- package/dist/authorization/model/workflow_instance.js.map +1 -1
- package/dist/authorization/organization-directory.d.ts.map +1 -1
- package/dist/authorization/organization-directory.js +3 -2
- package/dist/authorization/organization-directory.js.map +1 -1
- package/dist/authorization/store-test-kit.d.ts +6 -0
- package/dist/authorization/store-test-kit.d.ts.map +1 -1
- package/dist/authorization/store-test-kit.js +62 -16
- package/dist/authorization/store-test-kit.js.map +1 -1
- package/dist/authorization/tuples.d.ts +32 -13
- package/dist/authorization/tuples.d.ts.map +1 -1
- package/dist/authorization/tuples.js +11 -3
- package/dist/authorization/tuples.js.map +1 -1
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +49 -24
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/config.d.ts +4 -3
- package/dist/boot/config.d.ts.map +1 -1
- package/dist/boot/config.js.map +1 -1
- package/dist/boot/skill-transfer-origin.d.ts +52 -0
- package/dist/boot/skill-transfer-origin.d.ts.map +1 -0
- package/dist/boot/skill-transfer-origin.js +54 -0
- package/dist/boot/skill-transfer-origin.js.map +1 -0
- package/dist/domain/agent/controller.d.ts.map +1 -1
- package/dist/domain/agent/controller.js +4 -4
- package/dist/domain/agent/controller.js.map +1 -1
- package/dist/domain/agentchannel/controller.d.ts.map +1 -1
- package/dist/domain/agentchannel/controller.js +1 -3
- package/dist/domain/agentchannel/controller.js.map +1 -1
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +1 -3
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentinstance/controller.d.ts.map +1 -1
- package/dist/domain/agentinstance/controller.js +4 -3
- package/dist/domain/agentinstance/controller.js.map +1 -1
- package/dist/domain/agentshare/constants.d.ts +11 -6
- package/dist/domain/agentshare/constants.d.ts.map +1 -1
- package/dist/domain/agentshare/constants.js +16 -8
- package/dist/domain/agentshare/constants.js.map +1 -1
- package/dist/domain/agentshare/controller.d.ts.map +1 -1
- package/dist/domain/agentshare/controller.js +1 -3
- package/dist/domain/agentshare/controller.js.map +1 -1
- package/dist/domain/agentshare/steps.d.ts +25 -18
- package/dist/domain/agentshare/steps.d.ts.map +1 -1
- package/dist/domain/agentshare/steps.js +142 -41
- package/dist/domain/agentshare/steps.js.map +1 -1
- package/dist/domain/environment/controller.d.ts.map +1 -1
- package/dist/domain/environment/controller.js +3 -2
- package/dist/domain/environment/controller.js.map +1 -1
- package/dist/domain/executioncontext/controller.d.ts.map +1 -1
- package/dist/domain/executioncontext/controller.js +1 -2
- package/dist/domain/executioncontext/controller.js.map +1 -1
- package/dist/domain/mcpserver/controller.d.ts.map +1 -1
- package/dist/domain/mcpserver/controller.js +4 -3
- package/dist/domain/mcpserver/controller.js.map +1 -1
- package/dist/domain/plugin/controller.d.ts +3 -7
- package/dist/domain/plugin/controller.d.ts.map +1 -1
- package/dist/domain/plugin/controller.js +11 -9
- package/dist/domain/plugin/controller.js.map +1 -1
- package/dist/domain/plugin/push.d.ts +5 -7
- package/dist/domain/plugin/push.d.ts.map +1 -1
- package/dist/domain/plugin/push.js +14 -8
- package/dist/domain/plugin/push.js.map +1 -1
- package/dist/domain/schedule/controller.d.ts.map +1 -1
- package/dist/domain/schedule/controller.js +1 -3
- package/dist/domain/schedule/controller.js.map +1 -1
- package/dist/domain/session/controller.d.ts.map +1 -1
- package/dist/domain/session/controller.js +2 -3
- package/dist/domain/session/controller.js.map +1 -1
- package/dist/domain/skill/constants.d.ts +26 -3
- package/dist/domain/skill/constants.d.ts.map +1 -1
- package/dist/domain/skill/constants.js +26 -3
- package/dist/domain/skill/constants.js.map +1 -1
- package/dist/domain/skill/controller.d.ts +6 -11
- package/dist/domain/skill/controller.d.ts.map +1 -1
- package/dist/domain/skill/controller.js +35 -22
- package/dist/domain/skill/controller.js.map +1 -1
- package/dist/domain/skill/push.d.ts +2 -2
- package/dist/domain/skill/push.d.ts.map +1 -1
- package/dist/domain/skill/push.js +2 -2
- package/dist/domain/skill/push.js.map +1 -1
- package/dist/domain/skill/transfer/handler.d.ts +17 -9
- package/dist/domain/skill/transfer/handler.d.ts.map +1 -1
- package/dist/domain/skill/transfer/handler.js +19 -8
- package/dist/domain/skill/transfer/handler.js.map +1 -1
- package/dist/domain/skill/transfer/slots.d.ts +26 -41
- package/dist/domain/skill/transfer/slots.d.ts.map +1 -1
- package/dist/domain/skill/transfer/slots.js +80 -87
- package/dist/domain/skill/transfer/slots.js.map +1 -1
- package/dist/domain/skill/transfer/staging.d.ts +48 -0
- package/dist/domain/skill/transfer/staging.d.ts.map +1 -0
- package/dist/domain/skill/transfer/staging.js +127 -0
- package/dist/domain/skill/transfer/staging.js.map +1 -0
- package/dist/domain/workflow/controller.d.ts.map +1 -1
- package/dist/domain/workflow/controller.js +6 -14
- package/dist/domain/workflow/controller.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.d.ts +1 -10
- package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.js +2 -3
- package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +2 -4
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
- package/dist/domain/workflowinstance/controller.js +4 -3
- package/dist/domain/workflowinstance/controller.js.map +1 -1
- package/dist/extensions/authorization-queries.d.ts +5 -6
- package/dist/extensions/authorization-queries.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +1 -1
- package/dist/extensions/resource-authorization.d.ts +2 -3
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +3 -12
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +10 -21
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +3 -9
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +11 -9
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +20 -178
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +43 -344
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/pipeline/steps/resolve-artifact-source.d.ts +11 -8
- package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -1
- package/dist/pipeline/steps/resolve-artifact-source.js +8 -4
- package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -1
- package/dist/pipeline/steps/visibility-gates.d.ts +27 -0
- package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -0
- package/dist/pipeline/steps/visibility-gates.js +139 -0
- package/dist/pipeline/steps/visibility-gates.js.map +1 -0
- package/dist/query/search/controller.js +1 -0
- package/dist/query/search/controller.js.map +1 -1
- package/dist/query/search/criteria.d.ts +5 -1
- package/dist/query/search/criteria.d.ts.map +1 -1
- package/dist/query/search/criteria.js +13 -3
- package/dist/query/search/criteria.js.map +1 -1
- package/dist/query/search/handler.d.ts +4 -5
- package/dist/query/search/handler.d.ts.map +1 -1
- package/dist/query/search/handler.js +6 -7
- package/dist/query/search/handler.js.map +1 -1
- package/dist/query/search/query-store.d.ts.map +1 -1
- package/dist/query/search/query-store.js +2 -0
- package/dist/query/search/query-store.js.map +1 -1
- package/dist/store/interface.d.ts +6 -3
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +1 -3
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +1 -35
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +9 -4
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +1 -3
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +1 -36
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +8 -4
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/artifactstorage/__tests__/artifact-storage.test.ts +36 -33
- package/src/artifactstorage/__tests__/r2-storage.test.ts +11 -13
- package/src/artifactstorage/artifact-storage.ts +37 -33
- package/src/artifactstorage/r2-storage.ts +6 -15
- package/src/authorization/README.md +26 -24
- package/src/authorization/__tests__/authorizer.test.ts +9 -10
- package/src/authorization/__tests__/derived-tuples.test.ts +11 -4
- package/src/authorization/__tests__/evaluator.test.ts +73 -14
- package/src/authorization/__tests__/facts.test.ts +2 -2
- package/src/authorization/__tests__/fixtures/fga/agent-instance-creation.fga.yaml +185 -0
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +98 -6
- package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +61 -4
- package/src/authorization/__tests__/fixtures/fga/mcp-server-authoring.fga.yaml +143 -0
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +21 -1
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +25 -1
- package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +3 -1
- package/src/authorization/__tests__/list-read-scope.test.ts +17 -18
- package/src/authorization/__tests__/store-tests.test.ts +8 -1
- package/src/authorization/__tests__/tuples.test.ts +11 -12
- package/src/authorization/authorizer.ts +9 -4
- package/src/authorization/derived-tuples.ts +31 -14
- package/src/authorization/evaluator.ts +44 -8
- package/src/authorization/list-read-scope.ts +11 -5
- package/src/authorization/model/agent.ts +5 -2
- package/src/authorization/model/agent_instance.ts +2 -0
- package/src/authorization/model/mcp_server.ts +2 -0
- package/src/authorization/model/plugin.ts +4 -1
- package/src/authorization/model/rewrite.ts +13 -8
- package/src/authorization/model/skill.ts +2 -0
- package/src/authorization/model/workflow.ts +2 -0
- package/src/authorization/model/workflow_instance.ts +2 -0
- package/src/authorization/organization-directory.ts +3 -1
- package/src/authorization/store-test-kit.ts +75 -16
- package/src/authorization/tuples.ts +39 -16
- package/src/boot/__tests__/skill-transfer-origin.test.ts +72 -0
- package/src/boot/compose.ts +62 -25
- package/src/boot/config.ts +4 -3
- package/src/boot/skill-transfer-origin.ts +76 -0
- package/src/domain/agent/__tests__/agent.test.ts +4 -11
- package/src/domain/agent/controller.ts +7 -7
- package/src/domain/agentchannel/__tests__/agentchannel.test.ts +48 -223
- package/src/domain/agentchannel/controller.ts +1 -6
- package/src/domain/agentexecution/controller.ts +1 -6
- package/src/domain/agentinstance/controller.ts +12 -6
- package/src/domain/agentshare/__tests__/agentshare.test.ts +172 -196
- package/src/domain/agentshare/__tests__/create-authorization.test.ts +31 -16
- package/src/domain/agentshare/constants.ts +26 -14
- package/src/domain/agentshare/controller.ts +1 -6
- package/src/domain/agentshare/steps.ts +194 -41
- package/src/domain/environment/controller.ts +8 -5
- package/src/domain/executioncontext/controller.ts +1 -5
- package/src/domain/mcpserver/__tests__/mcpserver.test.ts +28 -115
- package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +18 -53
- package/src/domain/mcpserver/controller.ts +12 -6
- package/src/domain/plugin/controller.ts +23 -18
- package/src/domain/plugin/push.ts +16 -8
- package/src/domain/schedule/controller.ts +1 -6
- package/src/domain/session/controller.ts +4 -12
- package/src/domain/skill/__tests__/skill.test.ts +5 -3
- package/src/domain/skill/__tests__/slots.test.ts +113 -60
- package/src/domain/skill/__tests__/staging.test.ts +304 -0
- package/src/domain/skill/constants.ts +28 -3
- package/src/domain/skill/controller.ts +51 -35
- package/src/domain/skill/push.ts +3 -3
- package/src/domain/skill/transfer/handler.ts +33 -15
- package/src/domain/skill/transfer/slots.ts +89 -100
- package/src/domain/skill/transfer/staging.ts +191 -0
- package/src/domain/workflow/controller.ts +10 -28
- package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/src/domain/workflow/validation/task-config-constraints.ts +3 -7
- package/src/domain/workflowexecution/controller.ts +2 -7
- package/src/domain/workflowinstance/controller.ts +12 -6
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +19 -32
- package/src/extensions/__tests__/extension-composition.test.ts +4 -4
- package/src/extensions/__tests__/list-read-scope-composed.test.ts +6 -9
- package/src/extensions/authorization-queries.ts +5 -6
- package/src/extensions/list-read-scope.ts +1 -1
- package/src/extensions/resource-authorization.ts +5 -3
- package/src/index.ts +14 -0
- package/src/pipeline/apiresource-meta.ts +10 -21
- package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +31 -18
- package/src/pipeline/steps/__tests__/visibility-gates.test.ts +187 -0
- package/src/pipeline/steps/authorization-tuples.ts +11 -9
- package/src/pipeline/steps/references.ts +70 -578
- package/src/pipeline/steps/resolve-artifact-source.ts +20 -13
- package/src/pipeline/steps/visibility-gates.ts +174 -0
- package/src/query/search/__tests__/criteria.test.ts +4 -0
- package/src/query/search/__tests__/query-store.test.ts +40 -11
- package/src/query/search/controller.ts +1 -0
- package/src/query/search/criteria.ts +14 -0
- package/src/query/search/handler.ts +7 -6
- package/src/query/search/query-store.ts +2 -0
- package/src/store/__tests__/store-contract.ts +51 -6
- package/src/store/interface.ts +6 -3
- package/src/store/postgres/__tests__/migrations.test.ts +6 -187
- package/src/store/postgres/__tests__/store-contract.test.ts +2 -0
- package/src/store/postgres/migrations.ts +1 -48
- package/src/store/postgres/store.ts +11 -4
- package/src/store/sqlite/__tests__/migrations.test.ts +5 -191
- package/src/store/sqlite/migrations.ts +1 -45
- package/src/store/sqlite/store.ts +10 -4
- package/src/transport/registry/__tests__/lanes.test.ts +1 -1
- package/dist/domain/workflow/agent-call-references.d.ts +0 -54
- package/dist/domain/workflow/agent-call-references.d.ts.map +0 -1
- package/dist/domain/workflow/agent-call-references.js +0 -97
- package/dist/domain/workflow/agent-call-references.js.map +0 -1
- package/dist/store/public-visibility-retired.d.ts +0 -67
- package/dist/store/public-visibility-retired.d.ts.map +0 -1
- package/dist/store/public-visibility-retired.js +0 -55
- package/dist/store/public-visibility-retired.js.map +0 -1
- package/src/domain/workflow/__tests__/agent-call-references.test.ts +0 -222
- package/src/domain/workflow/agent-call-references.ts +0 -157
- package/src/pipeline/__tests__/supports-visibility.test.ts +0 -112
- package/src/pipeline/steps/__tests__/references.test.ts +0 -703
- package/src/store/__tests__/public-visibility-retired.test.ts +0 -127
- package/src/store/public-visibility-retired.ts +0 -119
|
@@ -58,17 +58,15 @@ export class ArtifactStorageNotFoundError extends Error {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* A staged upload minted by presignPut: the URL receives the bytes,
|
|
62
|
-
*
|
|
63
|
-
* short-lived by contract — the local lane sweeps them on TTL
|
|
64
|
-
* boot;
|
|
65
|
-
* prefix (the §6b driver-side sweep expectation).
|
|
61
|
+
* A staged upload minted by presignPut: the URL receives the bytes, which
|
|
62
|
+
* the caller reads back through download() under the key IT named. Staged
|
|
63
|
+
* blobs are short-lived by contract — the local lane sweeps them on TTL
|
|
64
|
+
* expiry and boot; a bucket deployment configures a lifecycle rule on the
|
|
65
|
+
* domain's staging prefix (the §6b driver-side sweep expectation).
|
|
66
66
|
*/
|
|
67
67
|
export interface PresignedUpload {
|
|
68
|
-
/** Accepts
|
|
68
|
+
/** Accepts an HTTP PUT of exactly the declared byte count. */
|
|
69
69
|
readonly url: string;
|
|
70
|
-
/** Driver key where the staged bytes land, readable via download(). */
|
|
71
|
-
readonly stagingKey: string;
|
|
72
70
|
/** The TTL actually granted, after per-driver clamping. */
|
|
73
71
|
readonly ttlMs: number;
|
|
74
72
|
}
|
|
@@ -98,18 +96,25 @@ export interface ArtifactStorage {
|
|
|
98
96
|
downloadFilename: string,
|
|
99
97
|
): Promise<string>;
|
|
100
98
|
/**
|
|
101
|
-
* A time-limited upload URL for a
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
99
|
+
* A time-limited upload URL for a blob of exactly declaredSizeBytes at
|
|
100
|
+
* the key the CALLER names (§6b). The key is the domain's: it chooses
|
|
101
|
+
* the staging prefix its sweep targets and the mapping from its wire
|
|
102
|
+
* reference, and reads the bytes back through download(key) — the
|
|
103
|
+
* driver never invents a key of its own. Per-driver semantics differ
|
|
104
|
+
* DELIBERATELY and are contract, not accident: the local backend rides
|
|
105
|
+
* the skill transfer lane's URL-as-credential slot mechanism
|
|
106
|
+
* (single-use, exact-size enforced by the lane, TTL clamped to the
|
|
107
|
+
* lane's slot TTL) and answers only on instances with a staged-upload
|
|
108
|
+
* lane wired — unwired instances throw the explicit not-configured
|
|
109
|
+
* error, never a silent no-op. The R2 backend presigns a PUT
|
|
110
|
+
* (repeatable within its TTL, size enforced by the signed
|
|
111
|
+
* Content-Length header, TTL clamped to the 7-day R2 maximum).
|
|
111
112
|
*/
|
|
112
|
-
presignPut(
|
|
113
|
+
presignPut(
|
|
114
|
+
key: string,
|
|
115
|
+
declaredSizeBytes: number,
|
|
116
|
+
ttlMs: number,
|
|
117
|
+
): Promise<PresignedUpload>;
|
|
113
118
|
/** Removes the artifact; missing is not an error. */
|
|
114
119
|
delete(key: string): Promise<void>;
|
|
115
120
|
/** Whether an artifact with the key exists. */
|
|
@@ -136,16 +141,16 @@ export type ArtifactStorageDriverFactory = () => ArtifactStorage;
|
|
|
136
141
|
* the shape it needs and stays ignorant of who provides it.
|
|
137
142
|
*/
|
|
138
143
|
export interface StagedUploadLane {
|
|
139
|
-
/** Reserves a single-use upload slot; returns its reference + TTL. */
|
|
140
|
-
mint(declaredSizeBytes: number): { ref: string; ttlMs: number };
|
|
141
|
-
/** The externally-reachable PUT URL for a minted reference. */
|
|
142
|
-
uploadUrl(ref: string): string;
|
|
143
144
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
145
|
+
* Reserves a single-use upload slot whose bytes land at `key` under this
|
|
146
|
+
* driver instance's root — the lane stages into the driver's own tree,
|
|
147
|
+
* so download(key) reads exactly what the lane received. Returns the
|
|
148
|
+
* externally-reachable PUT URL and the TTL the lane grants.
|
|
147
149
|
*/
|
|
148
|
-
|
|
150
|
+
reserve(
|
|
151
|
+
key: string,
|
|
152
|
+
declaredSizeBytes: number,
|
|
153
|
+
): { url: string; ttlMs: number };
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
export interface ArtifactStorageConfig {
|
|
@@ -259,6 +264,7 @@ export class LocalArtifactStorage implements ArtifactStorage {
|
|
|
259
264
|
}
|
|
260
265
|
|
|
261
266
|
async presignPut(
|
|
267
|
+
key: string,
|
|
262
268
|
declaredSizeBytes: number,
|
|
263
269
|
_ttlMs: number,
|
|
264
270
|
): Promise<PresignedUpload> {
|
|
@@ -267,15 +273,13 @@ export class LocalArtifactStorage implements ArtifactStorage {
|
|
|
267
273
|
"local presigned uploads not configured - no staged-upload lane is wired to this store instance",
|
|
268
274
|
);
|
|
269
275
|
}
|
|
276
|
+
// The key must be one this instance can read back, or the lane would
|
|
277
|
+
// stage bytes download(key) can never reach.
|
|
278
|
+
this.resolveWithinRoot(key);
|
|
270
279
|
// The lane's slot TTL governs, not the caller's ask — the slot
|
|
271
280
|
// registry sweeps on ITS clock, and a URL outliving its slot would be
|
|
272
281
|
// a credential for nothing.
|
|
273
|
-
|
|
274
|
-
return {
|
|
275
|
-
url: this.stagedUploadLane.uploadUrl(ref),
|
|
276
|
-
stagingKey: this.stagedUploadLane.stagedKey(ref),
|
|
277
|
-
ttlMs,
|
|
278
|
-
};
|
|
282
|
+
return this.stagedUploadLane.reserve(key, declaredSizeBytes);
|
|
279
283
|
}
|
|
280
284
|
|
|
281
285
|
async getSignedUrl(
|
|
@@ -9,8 +9,6 @@
|
|
|
9
9
|
* that have logic: config validation copy, the 7-day presign clamp, the
|
|
10
10
|
* signed Content-Disposition, and the not-found mapping.
|
|
11
11
|
*/
|
|
12
|
-
import { randomBytes } from "node:crypto";
|
|
13
|
-
|
|
14
12
|
import {
|
|
15
13
|
DeleteObjectCommand,
|
|
16
14
|
GetObjectCommand,
|
|
@@ -30,13 +28,6 @@ import {
|
|
|
30
28
|
/** Go: "R2 has a maximum expiration of 7 days" — presigns clamp here. */
|
|
31
29
|
export const R2_MAX_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
32
30
|
|
|
33
|
-
/**
|
|
34
|
-
* Key prefix for presignPut staging blobs (§6b). Pinned as the surface a
|
|
35
|
-
* deployment's bucket lifecycle rule targets: the driver mints under it,
|
|
36
|
-
* operations sweeps it — changing it orphans staged blobs from the sweep.
|
|
37
|
-
*/
|
|
38
|
-
export const R2_STAGING_PREFIX = "staging/";
|
|
39
|
-
|
|
40
31
|
/**
|
|
41
32
|
* Go get_content/get_download_url wrap their storage calls in a 30s
|
|
42
33
|
* context timeout. The TS ArtifactStorage interface carries no signal, so
|
|
@@ -167,17 +158,17 @@ export class R2ArtifactStorage implements ArtifactStorage {
|
|
|
167
158
|
}
|
|
168
159
|
|
|
169
160
|
async presignPut(
|
|
161
|
+
key: string,
|
|
170
162
|
declaredSizeBytes: number,
|
|
171
163
|
ttlMs: number,
|
|
172
164
|
): Promise<PresignedUpload> {
|
|
173
165
|
const clampedMs = Math.min(ttlMs, R2_MAX_EXPIRATION_MS);
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
const stagingKey = `${R2_STAGING_PREFIX}${randomBytes(16).toString("hex")}`;
|
|
166
|
+
// The key is the caller's: the domain names its staging prefix (the
|
|
167
|
+
// surface a bucket lifecycle rule sweeps) and keeps the unguessable
|
|
168
|
+
// part of the URL-as-credential in the reference it hands the client.
|
|
178
169
|
const command = new PutObjectCommand({
|
|
179
170
|
Bucket: this.bucket,
|
|
180
|
-
Key:
|
|
171
|
+
Key: key,
|
|
181
172
|
// Signed into the URL: a PUT whose body disagrees with the declared
|
|
182
173
|
// size fails the signature check — R2's arm of the exact-size
|
|
183
174
|
// contract the local lane enforces by counting bytes.
|
|
@@ -187,7 +178,7 @@ export class R2ArtifactStorage implements ArtifactStorage {
|
|
|
187
178
|
const url = await this.presign(this.client, command, {
|
|
188
179
|
expiresIn: Math.floor(clampedMs / 1000),
|
|
189
180
|
});
|
|
190
|
-
return { url,
|
|
181
|
+
return { url, ttlMs: clampedMs };
|
|
191
182
|
} catch (error) {
|
|
192
183
|
throw new Error(`r2 presign failed: ${errorText(error)}`, { cause: error });
|
|
193
184
|
}
|
|
@@ -34,9 +34,9 @@ editions; the cloud stores what open source computes.
|
|
|
34
34
|
`spec.execution_visibility`).
|
|
35
35
|
- `tuples.ts` — the tuple vocabulary (object, relation, subject; the string
|
|
36
36
|
notation), the `Person` type (the caller as the model sees them: account id
|
|
37
|
-
plus the aliases a creator stamp may carry)
|
|
38
|
-
|
|
39
|
-
the
|
|
37
|
+
plus the aliases a creator stamp may carry), `CheckContext` (the
|
|
38
|
+
`allow_public` parameter: `allow: true` on a point check, `false` in a listing
|
|
39
|
+
— the cloud's own posture).
|
|
40
40
|
- `person.ts` — the one construction of a `Person`: `resolvePerson` reads the
|
|
41
41
|
caller's account through the port the way whoAmI does, `personFor` builds the
|
|
42
42
|
aliases (the account id and the issuer subject; an email is nobody's) and
|
|
@@ -70,8 +70,8 @@ editions; the cloud stores what open source computes.
|
|
|
70
70
|
|
|
71
71
|
- `authorizer.ts` — the `Authorizer` driver, arm for arm the cloud's
|
|
72
72
|
(`stigmer-cloud src/authorizer/fga-authorizer.ts`): the four pre-check denials
|
|
73
|
-
with the Java copy; a kind this edition does not serve denied (
|
|
74
|
-
|
|
73
|
+
with the Java copy; a kind this edition does not serve denied (so nobody sets
|
|
74
|
+
public visibility on a self-host); the target loaded once through the source;
|
|
75
75
|
`not-found` for a missing row except on the kinds the cloud never probes
|
|
76
76
|
(`NOT_FOUND_EXEMPT_KINDS`: `identity_account`, `iam_policy` — account ids
|
|
77
77
|
cannot be enumerated); the model's answer with an empty reason on a denial so
|
|
@@ -87,14 +87,15 @@ editions; the cloud stores what open source computes.
|
|
|
87
87
|
counts against the schedule instead of retrying forever.
|
|
88
88
|
- `list-read-scope.ts` — the `ListReadScope` driver, the cloud's twin
|
|
89
89
|
(`stigmer-cloud src/iam/list-read-scope.ts`): every candidate a list lane
|
|
90
|
-
offers is answered by `can_view
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
kind is a consumer
|
|
90
|
+
offers is answered by `can_view` under the listing context (`allow: false`,
|
|
91
|
+
the public wildcard suppressed) — one evaluator walk per candidate over one
|
|
92
|
+
source seeded with the candidates' facts, so no candidate row is read twice
|
|
93
|
+
and a parent hop reads each distinct parent once; the enumeration verb
|
|
94
|
+
(search, recent activity, the two execution summaries — the console library
|
|
95
|
+
rides it) scans the kind and evaluates the same way, a row that does not
|
|
96
|
+
decode skipped; the `internal` class keeps everything (the in-process skip); a
|
|
97
|
+
fault throws and is never an empty answer; an undeclared kind is a consumer
|
|
98
|
+
bug, loud.
|
|
98
99
|
- `posture.ts` — the three postures, named once for the composition root and the
|
|
99
100
|
boot log.
|
|
100
101
|
|
|
@@ -109,14 +110,15 @@ kind. `model/__tests__/registry.test.ts` pins the declared set to the
|
|
|
109
110
|
open-source tier and each kind's wire permissions to its file;
|
|
110
111
|
`__tests__/wire-permissions.test.ts` pins that every static `(kind, permission)`
|
|
111
112
|
a served RPC asks about is a declared relation. The rest pin the machinery:
|
|
112
|
-
alias matching, the memo, the bounds, the source and
|
|
113
|
-
both store drivers. The four drivers are pinned arm by
|
|
114
|
-
(`__tests__/authorizer.test.ts`,
|
|
115
|
-
`
|
|
116
|
-
cells first: the outsider, the
|
|
117
|
-
|
|
118
|
-
at the wire over three real
|
|
119
|
-
(`extensions/__tests__/built-in-authorization-composed.test.ts`, the list
|
|
120
|
-
included, and the two-boot proof that the sole person's lists are
|
|
121
|
-
with and without the scope), and the scope's cost is measured
|
|
122
|
-
assumed (`list-read-scope.measure.test.ts`, gated on
|
|
113
|
+
alias matching, the wildcard's condition, the memo, the bounds, the source and
|
|
114
|
+
the two derived rules on both store drivers. The four drivers are pinned arm by
|
|
115
|
+
arm on both store drivers (`__tests__/authorizer.test.ts`,
|
|
116
|
+
`organization-directory.test.ts`, `schedule-fire-caller.test.ts`,
|
|
117
|
+
`list-read-scope.test.ts` — the adversarial cells first: the outsider, the
|
|
118
|
+
viewer rung, the admin who does not read members' conversations, the orphaned
|
|
119
|
+
execution, the memory with no subject), the posture at the wire over three real
|
|
120
|
+
boots (`extensions/__tests__/built-in-authorization-composed.test.ts`, the list
|
|
121
|
+
lanes included, and the two-boot proof that the sole person's lists are
|
|
122
|
+
byte-identical with and without the scope), and the scope's cost is measured
|
|
123
|
+
rather than assumed (`list-read-scope.measure.test.ts`, gated on
|
|
124
|
+
`AUTHORIZATION_MEASURE=1`).
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Pins the built-in Authorizer arm by arm, on both store drivers, against
|
|
3
3
|
* the cloud's driver it mirrors (stigmer-cloud src/authorizer/
|
|
4
4
|
* fga-authorizer.ts): the four pre-check denials with the Java copy; the
|
|
5
|
-
* unserved-kind denial (
|
|
5
|
+
* unserved-kind denial (the server-side half of "nobody sets public
|
|
6
|
+
visibility on a self-host"); not-found for a
|
|
6
7
|
* missing target and a DENIAL for a missing row of an exempt kind (the
|
|
7
8
|
* cloud's probe scope, so account ids cannot be enumerated); allow and
|
|
8
9
|
* deny from the model over a seeded organization — the owner, an admin, a
|
|
@@ -221,11 +222,9 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
221
222
|
await grant(orgRole(FOUNDER.accountId, "owner", "acme"));
|
|
222
223
|
await grant(orgRole(ADMIN.accountId, "admin", "acme"));
|
|
223
224
|
await grant(orgRole(MEMBER.accountId, "member", "acme"));
|
|
224
|
-
// The founder's blueprints: one private, one org-visible,
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
// founder's RAW subject (a row a 3.14.x verifier wrote), the
|
|
228
|
-
// others with the id.
|
|
225
|
+
// The founder's blueprints: one private, one org-visible, one
|
|
226
|
+
// public; the org-visible one stamped with the founder's RAW
|
|
227
|
+
// subject (a row a 3.14.x verifier wrote), the others with the id.
|
|
229
228
|
await seed("agent", "agt_private", {
|
|
230
229
|
org: "acme",
|
|
231
230
|
visibility: ApiResourceVisibility.visibility_private,
|
|
@@ -288,10 +287,10 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
288
287
|
UNKNOWN_KIND_DENY_REASON,
|
|
289
288
|
],
|
|
290
289
|
[
|
|
291
|
-
"a kind this edition does not serve (platform — nobody
|
|
290
|
+
"a kind this edition does not serve (platform — nobody sets public visibility)",
|
|
292
291
|
resolved(FOUNDER),
|
|
293
292
|
check(
|
|
294
|
-
IamPermission.
|
|
293
|
+
IamPermission.can_set_public_visibility,
|
|
295
294
|
ApiResourceKind.platform,
|
|
296
295
|
"stigmer",
|
|
297
296
|
),
|
|
@@ -466,7 +465,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
466
465
|
});
|
|
467
466
|
});
|
|
468
467
|
|
|
469
|
-
it("an unprovisioned subject reads
|
|
468
|
+
it("an unprovisioned subject reads a PUBLIC agent (the point-check context honours the wildcard) and nothing private", async () => {
|
|
470
469
|
const auth = authorizer();
|
|
471
470
|
expect(
|
|
472
471
|
await auth.authorize(
|
|
@@ -477,7 +476,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
477
476
|
"agt_public",
|
|
478
477
|
),
|
|
479
478
|
),
|
|
480
|
-
).toEqual({ kind: "
|
|
479
|
+
).toEqual({ kind: "allow" });
|
|
481
480
|
expect(
|
|
482
481
|
await auth.authorize(
|
|
483
482
|
idpShaped(STRANGER),
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* built-in authorizer: which tuples a stored row stands for, in exactly
|
|
4
4
|
* the shapes the cloud's tuple driver writes (stigmer-cloud
|
|
5
5
|
* iam/tuple-lifecycle.ts: `organization:<org>#viewer` for the org level,
|
|
6
|
-
* the
|
|
6
|
+
* the conditional `identity_account:*` for public, the owner by the
|
|
7
|
+
* kind's attribution, the parent links by `kind_meta`). Two facts are the
|
|
7
8
|
* OSS edition's own and are pinned here by name: the organization's owner
|
|
8
9
|
* is a ROW (2b's role lifecycle), never derived from its creator stamp,
|
|
9
10
|
* or a revoked founder would stay owner; and a stamp that names no person
|
|
@@ -95,7 +96,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
95
96
|
]);
|
|
96
97
|
});
|
|
97
98
|
|
|
98
|
-
it("a
|
|
99
|
+
it("a public blueprint adds the conditional wildcard AND keeps the org floor", () => {
|
|
99
100
|
expect(
|
|
100
101
|
derivedFor("skill", {
|
|
101
102
|
visibility: ApiResourceVisibility.visibility_public,
|
|
@@ -103,6 +104,8 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
103
104
|
).toEqual([
|
|
104
105
|
"skill:skill-1#organization@organization:acme",
|
|
105
106
|
"skill:skill-1#owner@identity_account:ida_carol",
|
|
107
|
+
"skill:skill-1#viewer@identity_account:* with allow_public",
|
|
108
|
+
"skill:skill-1#viewer@organization:acme#viewer",
|
|
106
109
|
]);
|
|
107
110
|
});
|
|
108
111
|
|
|
@@ -163,7 +166,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
163
166
|
).toEqual(["memory:memory-1#organization@organization:acme"]);
|
|
164
167
|
});
|
|
165
168
|
|
|
166
|
-
it("an environment carries its creator tuple
|
|
169
|
+
it("an environment carries its creator tuple, an org-viewer at org level, and NO public wildcard (the kind's ceiling)", () => {
|
|
167
170
|
expect(
|
|
168
171
|
derivedFor("environment", {
|
|
169
172
|
visibility: ApiResourceVisibility.visibility_org,
|
|
@@ -176,7 +179,7 @@ describe("deriveTuples — the cloud driver's shapes, from the row", () => {
|
|
|
176
179
|
]);
|
|
177
180
|
expect(
|
|
178
181
|
derivedFor("environment", {
|
|
179
|
-
visibility: ApiResourceVisibility.
|
|
182
|
+
visibility: ApiResourceVisibility.visibility_public,
|
|
180
183
|
}),
|
|
181
184
|
).toEqual([
|
|
182
185
|
"environment:environment-1#organization@organization:acme",
|
|
@@ -506,6 +509,9 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
506
509
|
object,
|
|
507
510
|
"can_view",
|
|
508
511
|
DAVE,
|
|
512
|
+
{
|
|
513
|
+
allow: false,
|
|
514
|
+
},
|
|
509
515
|
),
|
|
510
516
|
).toBe(true);
|
|
511
517
|
expect(rowReads).toBe(1);
|
|
@@ -701,6 +707,7 @@ describe.each(driverFixtures(SEEDED_KINDS))(
|
|
|
701
707
|
parseObjectRef(object),
|
|
702
708
|
relation,
|
|
703
709
|
person,
|
|
710
|
+
{ allow: true },
|
|
704
711
|
);
|
|
705
712
|
}
|
|
706
713
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pins the evaluator's semantics the store tests cannot express (the
|
|
3
3
|
* cloud's `.fga.yaml` documents prove the model's answers; this file
|
|
4
|
-
* proves the machinery under them): how a person matches a tuple,
|
|
5
|
-
* direct tuple outside the line's
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* proves the machinery under them): how a person matches a tuple, what
|
|
5
|
+
* the `allow_public` context does, that a direct tuple outside the line's
|
|
6
|
+
* type restriction is ignored (model drift fails closed), how far a
|
|
7
|
+
* resolution may walk, and that a declaration cycle or an undeclared
|
|
8
|
+
* target is a thrown fault and never a silent deny.
|
|
8
9
|
*
|
|
9
10
|
* The fixture source is the in-memory one the store-test kit uses, so the
|
|
10
11
|
* two proofs share one tuple vocabulary. Where a case needs a shape the
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
direct,
|
|
30
31
|
from,
|
|
31
32
|
objectOf,
|
|
33
|
+
publicWith,
|
|
32
34
|
union,
|
|
33
35
|
usersetOf,
|
|
34
36
|
} from "../model/rewrite.js";
|
|
@@ -54,17 +56,22 @@ function person(accountId: string, ...aliases: string[]): Person {
|
|
|
54
56
|
return { accountId, aliases: new Set([accountId, ...aliases]) };
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
const RESOLVE = { allow: true };
|
|
60
|
+
const LIST = { allow: false };
|
|
61
|
+
|
|
57
62
|
async function allowed(
|
|
58
63
|
source: TupleSource,
|
|
59
64
|
object: string,
|
|
60
65
|
relation: string,
|
|
61
66
|
who: Person,
|
|
67
|
+
context = RESOLVE,
|
|
62
68
|
): Promise<boolean> {
|
|
63
69
|
return checkRelation(
|
|
64
70
|
{ model: builtInModel, source },
|
|
65
71
|
parseObjectRef(object),
|
|
66
72
|
relation,
|
|
67
73
|
who,
|
|
74
|
+
context,
|
|
68
75
|
);
|
|
69
76
|
}
|
|
70
77
|
|
|
@@ -93,17 +100,67 @@ describe("a person against a direct tuple", () => {
|
|
|
93
100
|
});
|
|
94
101
|
});
|
|
95
102
|
|
|
96
|
-
describe("
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
describe("the public wildcard and its condition", () => {
|
|
104
|
+
const publicViewer = (object: string): Tuple => ({
|
|
105
|
+
object: parseObjectRef(object),
|
|
106
|
+
relation: "viewer",
|
|
107
|
+
subject: {
|
|
108
|
+
form: "wildcard",
|
|
109
|
+
type: "identity_account",
|
|
110
|
+
condition: "allow_public",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const source = newInMemoryTupleSource([
|
|
114
|
+
tuple("agent:open#organization@organization:acme"),
|
|
115
|
+
publicViewer("agent:open"),
|
|
116
|
+
]);
|
|
117
|
+
const stranger = person("ida_mallory");
|
|
118
|
+
|
|
119
|
+
it("reads for anyone on a point check (the cloud's `allow: true`) and for nobody in a listing (`allow: false`)", async () => {
|
|
104
120
|
expect(await allowed(source, "agent:open", "can_view", stranger)).toBe(
|
|
105
|
-
|
|
121
|
+
true,
|
|
106
122
|
);
|
|
123
|
+
expect(
|
|
124
|
+
await allowed(source, "agent:open", "can_view", stranger, LIST),
|
|
125
|
+
).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("ignores a wildcard tuple that carries no condition where the line demands one — a tuple the cloud could never have written", async () => {
|
|
129
|
+
const bare = newInMemoryTupleSource([
|
|
130
|
+
tuple("agent:open#viewer@identity_account:*"),
|
|
131
|
+
]);
|
|
132
|
+
expect(await allowed(bare, "agent:open", "can_view", stranger)).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("is a thrown fault under a condition the transcript names but the evaluator does not know — a model that grew a condition", async () => {
|
|
136
|
+
const grown = declareKind({
|
|
137
|
+
kind: ApiResourceKind.agent,
|
|
138
|
+
schema: AgentSchema,
|
|
139
|
+
source: "test/grown.fga",
|
|
140
|
+
relations: [
|
|
141
|
+
["viewer", direct(publicWith("identity_account", "after_hours"))],
|
|
142
|
+
],
|
|
143
|
+
});
|
|
144
|
+
const afterHours = newInMemoryTupleSource([
|
|
145
|
+
{
|
|
146
|
+
object: parseObjectRef("agent:open"),
|
|
147
|
+
relation: "viewer",
|
|
148
|
+
subject: {
|
|
149
|
+
form: "wildcard",
|
|
150
|
+
type: "identity_account",
|
|
151
|
+
condition: "after_hours",
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
]);
|
|
155
|
+
await expect(
|
|
156
|
+
checkRelation(
|
|
157
|
+
{ model: newModel([grown]), source: afterHours },
|
|
158
|
+
parseObjectRef("agent:open"),
|
|
159
|
+
"viewer",
|
|
160
|
+
stranger,
|
|
161
|
+
RESOLVE,
|
|
162
|
+
),
|
|
163
|
+
).rejects.toMatchObject({ reason: "unknown-condition" });
|
|
107
164
|
});
|
|
108
165
|
});
|
|
109
166
|
|
|
@@ -220,6 +277,7 @@ describe("the walk itself", () => {
|
|
|
220
277
|
parseObjectRef("agent:n0"),
|
|
221
278
|
"next",
|
|
222
279
|
person("ida_nobody"),
|
|
280
|
+
RESOLVE,
|
|
223
281
|
),
|
|
224
282
|
).rejects.toMatchObject({ reason: "resolution-depth-exceeded" });
|
|
225
283
|
});
|
|
@@ -240,6 +298,7 @@ describe("the walk itself", () => {
|
|
|
240
298
|
parseObjectRef("agent:x"),
|
|
241
299
|
"a",
|
|
242
300
|
person("ida_nobody"),
|
|
301
|
+
RESOLVE,
|
|
243
302
|
),
|
|
244
303
|
).rejects.toBeInstanceOf(AuthorizationEvaluationError);
|
|
245
304
|
});
|
|
@@ -273,7 +332,7 @@ describe("declareKind validates a transcript at load", () => {
|
|
|
273
332
|
source: "test/bad.fga",
|
|
274
333
|
relations: [
|
|
275
334
|
["viewer", direct(objectOf("identity_account"))],
|
|
276
|
-
["viewer", direct(
|
|
335
|
+
["viewer", direct(publicWith("identity_account", "allow_public"))],
|
|
277
336
|
],
|
|
278
337
|
}),
|
|
279
338
|
).toThrow("declared twice");
|
|
@@ -50,7 +50,7 @@ describe("rowFactsOf against the tuple lifecycle's own resolution", () => {
|
|
|
50
50
|
for (const visibility of [
|
|
51
51
|
ApiResourceVisibility.visibility_private,
|
|
52
52
|
ApiResourceVisibility.visibility_org,
|
|
53
|
-
ApiResourceVisibility.
|
|
53
|
+
ApiResourceVisibility.visibility_public,
|
|
54
54
|
]) {
|
|
55
55
|
it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the same parent links and visibility shapes`, () => {
|
|
56
56
|
const row = fixtureRow(declaration, {
|
|
@@ -133,7 +133,7 @@ describe("a list candidate against the loaded row — the facts' two producers",
|
|
|
133
133
|
for (const visibility of [
|
|
134
134
|
ApiResourceVisibility.visibility_private,
|
|
135
135
|
ApiResourceVisibility.visibility_org,
|
|
136
|
-
ApiResourceVisibility.
|
|
136
|
+
ApiResourceVisibility.visibility_public,
|
|
137
137
|
]) {
|
|
138
138
|
it(`${declaration.type} at ${ApiResourceVisibility[visibility]}: the candidate the helper builds carries the facts the driver derives from`, async () => {
|
|
139
139
|
const row = fixtureRow(declaration, {
|