@stigmer/server 3.40.1 → 3.41.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/authorization/authorizer.d.ts +16 -10
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +17 -9
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/derived-tuples.d.ts +7 -3
- package/dist/authorization/derived-tuples.d.ts.map +1 -1
- package/dist/authorization/derived-tuples.js +62 -6
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +11 -7
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +16 -10
- package/dist/authorization/evaluator.js.map +1 -1
- package/dist/authorization/list-read-scope.d.ts +4 -0
- package/dist/authorization/list-read-scope.d.ts.map +1 -1
- package/dist/authorization/list-read-scope.js +1 -0
- package/dist/authorization/list-read-scope.js.map +1 -1
- package/dist/authorization/model/data/authorization-model.json +830 -67
- package/dist/authorization/model/execution-viewer.d.ts.map +1 -1
- package/dist/authorization/model/execution-viewer.js +26 -24
- package/dist/authorization/model/execution-viewer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -1
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +4 -1
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +5 -3
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/organization-directory.d.ts +44 -0
- package/dist/authorization/organization-directory.d.ts.map +1 -1
- package/dist/authorization/organization-directory.js +1 -0
- package/dist/authorization/organization-directory.js.map +1 -1
- package/dist/authorization/person.d.ts +14 -1
- package/dist/authorization/person.d.ts.map +1 -1
- package/dist/authorization/person.js +16 -0
- package/dist/authorization/person.js.map +1 -1
- package/dist/authorization/policy-check.d.ts +52 -0
- package/dist/authorization/policy-check.d.ts.map +1 -0
- package/dist/authorization/policy-check.js +35 -0
- package/dist/authorization/policy-check.js.map +1 -0
- package/dist/authorization/posture.d.ts +30 -4
- package/dist/authorization/posture.d.ts.map +1 -1
- package/dist/authorization/posture.js +58 -0
- package/dist/authorization/posture.js.map +1 -1
- package/dist/authorization/resource-creators.d.ts +4 -0
- package/dist/authorization/resource-creators.d.ts.map +1 -0
- package/dist/authorization/resource-creators.js +44 -0
- package/dist/authorization/resource-creators.js.map +1 -0
- package/dist/authorization/trusted-local-authorizer.d.ts +9 -0
- package/dist/authorization/trusted-local-authorizer.d.ts.map +1 -0
- package/dist/authorization/trusted-local-authorizer.js +70 -0
- package/dist/authorization/trusted-local-authorizer.js.map +1 -0
- package/dist/authorization/tuples.d.ts +12 -0
- package/dist/authorization/tuples.d.ts.map +1 -1
- package/dist/authorization/tuples.js +3 -0
- package/dist/authorization/tuples.js.map +1 -1
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +132 -43
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/config.d.ts +22 -7
- package/dist/boot/config.d.ts.map +1 -1
- package/dist/boot/config.js +2 -1
- package/dist/boot/config.js.map +1 -1
- package/dist/boot/inprocess.d.ts.map +1 -1
- package/dist/boot/inprocess.js +10 -4
- package/dist/boot/inprocess.js.map +1 -1
- package/dist/boot/list-indexes.d.ts.map +1 -1
- package/dist/boot/list-indexes.js +6 -1
- package/dist/boot/list-indexes.js.map +1 -1
- package/dist/boot/logger.d.ts +3 -1
- package/dist/boot/logger.d.ts.map +1 -1
- package/dist/boot/logger.js +3 -1
- package/dist/boot/logger.js.map +1 -1
- package/dist/boot/oauth-redirect-uri.d.ts +33 -12
- package/dist/boot/oauth-redirect-uri.d.ts.map +1 -1
- package/dist/boot/oauth-redirect-uri.js +43 -14
- package/dist/boot/oauth-redirect-uri.js.map +1 -1
- package/dist/boot/skill-transfer-origin.d.ts +46 -14
- package/dist/boot/skill-transfer-origin.d.ts.map +1 -1
- package/dist/boot/skill-transfer-origin.js +53 -13
- package/dist/boot/skill-transfer-origin.js.map +1 -1
- package/dist/domain/agentchannel/steps.d.ts +8 -6
- package/dist/domain/agentchannel/steps.d.ts.map +1 -1
- package/dist/domain/agentchannel/steps.js +9 -7
- package/dist/domain/agentchannel/steps.js.map +1 -1
- package/dist/domain/agentexecution/controller.d.ts +7 -0
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +1 -1
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentexecution/create-steps.d.ts +26 -12
- package/dist/domain/agentexecution/create-steps.d.ts.map +1 -1
- package/dist/domain/agentexecution/create-steps.js +61 -43
- package/dist/domain/agentexecution/create-steps.js.map +1 -1
- package/dist/domain/agentexecution/submit-approval.d.ts.map +1 -1
- package/dist/domain/agentexecution/submit-approval.js +9 -6
- package/dist/domain/agentexecution/submit-approval.js.map +1 -1
- package/dist/domain/agentexecution/submit-file-decision.d.ts.map +1 -1
- package/dist/domain/agentexecution/submit-file-decision.js +5 -4
- package/dist/domain/agentexecution/submit-file-decision.js.map +1 -1
- package/dist/domain/agentshare/steps.d.ts +5 -3
- package/dist/domain/agentshare/steps.d.ts.map +1 -1
- package/dist/domain/agentshare/steps.js +6 -4
- package/dist/domain/agentshare/steps.js.map +1 -1
- package/dist/domain/apikey/verifier.d.ts +7 -0
- package/dist/domain/apikey/verifier.d.ts.map +1 -1
- package/dist/domain/apikey/verifier.js +34 -1
- package/dist/domain/apikey/verifier.js.map +1 -1
- package/dist/domain/channelapp/controller.d.ts +4 -3
- package/dist/domain/channelapp/controller.d.ts.map +1 -1
- package/dist/domain/channelapp/controller.js.map +1 -1
- package/dist/domain/executioncontext/steps.d.ts +2 -1
- package/dist/domain/executioncontext/steps.d.ts.map +1 -1
- package/dist/domain/executioncontext/steps.js +2 -1
- package/dist/domain/executioncontext/steps.js.map +1 -1
- package/dist/domain/iampolicy/access-lists.d.ts.map +1 -1
- package/dist/domain/iampolicy/access-lists.js +57 -2
- package/dist/domain/iampolicy/access-lists.js.map +1 -1
- package/dist/domain/iampolicy/change.d.ts +53 -0
- package/dist/domain/iampolicy/change.d.ts.map +1 -0
- package/dist/domain/iampolicy/change.js +44 -0
- package/dist/domain/iampolicy/change.js.map +1 -0
- package/dist/domain/iampolicy/constants.d.ts +6 -0
- package/dist/domain/iampolicy/constants.d.ts.map +1 -1
- package/dist/domain/iampolicy/constants.js +6 -0
- package/dist/domain/iampolicy/constants.js.map +1 -1
- package/dist/domain/iampolicy/controller.d.ts.map +1 -1
- package/dist/domain/iampolicy/controller.js +9 -5
- package/dist/domain/iampolicy/controller.js.map +1 -1
- package/dist/domain/iampolicy/grant-path.d.ts +31 -13
- package/dist/domain/iampolicy/grant-path.d.ts.map +1 -1
- package/dist/domain/iampolicy/grant-path.js +216 -19
- package/dist/domain/iampolicy/grant-path.js.map +1 -1
- package/dist/domain/iampolicy/membership.d.ts +11 -3
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +18 -13
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/iampolicy/resource-store.d.ts.map +1 -1
- package/dist/domain/iampolicy/resource-store.js +4 -0
- package/dist/domain/iampolicy/resource-store.js.map +1 -1
- package/dist/domain/iampolicy/role-lifecycle.d.ts.map +1 -1
- package/dist/domain/iampolicy/role-lifecycle.js +2 -2
- package/dist/domain/iampolicy/role-lifecycle.js.map +1 -1
- package/dist/domain/iampolicy/roles.d.ts.map +1 -1
- package/dist/domain/iampolicy/roles.js +7 -0
- package/dist/domain/iampolicy/roles.js.map +1 -1
- package/dist/domain/iampolicy/steps.d.ts +4 -3
- package/dist/domain/iampolicy/steps.d.ts.map +1 -1
- package/dist/domain/iampolicy/steps.js +7 -7
- package/dist/domain/iampolicy/steps.js.map +1 -1
- package/dist/domain/iampolicy/store-contract.d.ts.map +1 -1
- package/dist/domain/iampolicy/store-contract.js +22 -1
- package/dist/domain/iampolicy/store-contract.js.map +1 -1
- package/dist/domain/iampolicy/store.d.ts +18 -5
- package/dist/domain/iampolicy/store.d.ts.map +1 -1
- package/dist/domain/iampolicy/store.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +15 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +17 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/resolve.d.ts +47 -0
- package/dist/domain/identityaccount/resolve.d.ts.map +1 -1
- package/dist/domain/identityaccount/resolve.js +38 -1
- package/dist/domain/identityaccount/resolve.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.d.ts.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +11 -1
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +2 -1
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +4 -3
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +2 -2
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +6 -1
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/mcpserver/connect-sandbox.d.ts +67 -0
- package/dist/domain/mcpserver/connect-sandbox.d.ts.map +1 -0
- package/dist/domain/mcpserver/connect-sandbox.js +64 -0
- package/dist/domain/mcpserver/connect-sandbox.js.map +1 -0
- package/dist/domain/mcpserver/connect.d.ts +42 -10
- package/dist/domain/mcpserver/connect.d.ts.map +1 -1
- package/dist/domain/mcpserver/connect.js +147 -40
- package/dist/domain/mcpserver/connect.js.map +1 -1
- package/dist/domain/mcpserver/controller.js +4 -2
- package/dist/domain/mcpserver/controller.js.map +1 -1
- package/dist/domain/mcpserver/engine.d.ts +26 -7
- package/dist/domain/mcpserver/engine.d.ts.map +1 -1
- package/dist/domain/mcpserver/engine.js.map +1 -1
- package/dist/domain/mcpserver/start-connect.d.ts +5 -0
- package/dist/domain/mcpserver/start-connect.d.ts.map +1 -1
- package/dist/domain/mcpserver/start-connect.js +38 -15
- package/dist/domain/mcpserver/start-connect.js.map +1 -1
- package/dist/domain/memory/controller.js +2 -1
- package/dist/domain/memory/controller.js.map +1 -1
- package/dist/domain/memory/list-index.d.ts +2 -0
- package/dist/domain/memory/list-index.d.ts.map +1 -0
- package/dist/domain/memory/list-index.js +31 -0
- package/dist/domain/memory/list-index.js.map +1 -0
- package/dist/domain/memory/queries.d.ts +10 -0
- package/dist/domain/memory/queries.d.ts.map +1 -0
- package/dist/domain/memory/queries.js +54 -0
- package/dist/domain/memory/queries.js.map +1 -0
- package/dist/domain/memory/steps.d.ts +13 -11
- package/dist/domain/memory/steps.d.ts.map +1 -1
- package/dist/domain/memory/steps.js +26 -57
- package/dist/domain/memory/steps.js.map +1 -1
- package/dist/domain/organization/steps.d.ts.map +1 -1
- package/dist/domain/organization/steps.js +1 -1
- package/dist/domain/organization/steps.js.map +1 -1
- package/dist/domain/platformclient/mint.d.ts.map +1 -1
- package/dist/domain/platformclient/mint.js +2 -2
- package/dist/domain/platformclient/mint.js.map +1 -1
- package/dist/domain/platformclient/verifier.d.ts.map +1 -1
- package/dist/domain/platformclient/verifier.js +6 -3
- package/dist/domain/platformclient/verifier.js.map +1 -1
- package/dist/domain/plugin/push.d.ts.map +1 -1
- package/dist/domain/plugin/push.js +1 -0
- package/dist/domain/plugin/push.js.map +1 -1
- package/dist/domain/schedule/steps.d.ts +3 -1
- package/dist/domain/schedule/steps.d.ts.map +1 -1
- package/dist/domain/schedule/steps.js +3 -1
- package/dist/domain/schedule/steps.js.map +1 -1
- package/dist/domain/skill/push.d.ts.map +1 -1
- package/dist/domain/skill/push.js +1 -0
- package/dist/domain/skill/push.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +27 -1
- package/dist/domain/workflowexecution/submit-approval.d.ts +5 -2
- package/dist/domain/workflowexecution/submit-approval.d.ts.map +1 -1
- package/dist/domain/workflowexecution/submit-approval.js +1 -1
- package/dist/domain/workflowexecution/submit-approval.js.map +1 -1
- package/dist/domain/workflowexecution/submit-file-decision.d.ts +5 -2
- package/dist/domain/workflowexecution/submit-file-decision.d.ts.map +1 -1
- package/dist/domain/workflowexecution/submit-file-decision.js +1 -1
- package/dist/domain/workflowexecution/submit-file-decision.js.map +1 -1
- package/dist/domain/workflowexecution/submit-workflow-task-approval.d.ts.map +1 -1
- package/dist/domain/workflowexecution/submit-workflow-task-approval.js +12 -1
- package/dist/domain/workflowexecution/submit-workflow-task-approval.js.map +1 -1
- package/dist/domain/workflowinstance/controller.d.ts +6 -3
- package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
- package/dist/domain/workflowinstance/controller.js +12 -7
- package/dist/domain/workflowinstance/controller.js.map +1 -1
- package/dist/domain/workflowinstance/steps.d.ts +31 -0
- package/dist/domain/workflowinstance/steps.d.ts.map +1 -1
- package/dist/domain/workflowinstance/steps.js +88 -1
- package/dist/domain/workflowinstance/steps.js.map +1 -1
- package/dist/extensions/composed-services.d.ts +56 -0
- package/dist/extensions/composed-services.d.ts.map +1 -0
- package/dist/extensions/composed-services.js +2 -0
- package/dist/extensions/composed-services.js.map +1 -0
- package/dist/extensions/drivers.d.ts +32 -1
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/identity.d.ts +4 -1
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js +4 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/registry.d.ts +37 -0
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +50 -0
- package/dist/extensions/registry.js.map +1 -1
- package/dist/extensions/resource-authorization.d.ts +78 -0
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/extensions/resource-row-reader.d.ts +43 -0
- package/dist/extensions/resource-row-reader.d.ts.map +1 -0
- package/dist/extensions/resource-row-reader.js +2 -0
- package/dist/extensions/resource-row-reader.js.map +1 -0
- package/dist/extensions/visitor-classifier.d.ts +41 -0
- package/dist/extensions/visitor-classifier.d.ts.map +1 -0
- package/dist/extensions/visitor-classifier.js +2 -0
- package/dist/extensions/visitor-classifier.js.map +1 -0
- package/dist/identity/oidc-userinfo.d.ts +6 -1
- package/dist/identity/oidc-userinfo.d.ts.map +1 -1
- package/dist/identity/oidc-userinfo.js.map +1 -1
- package/dist/identity/oidc-verifier.d.ts.map +1 -1
- package/dist/identity/oidc-verifier.js +37 -8
- package/dist/identity/oidc-verifier.js.map +1 -1
- package/dist/index.d.ts +14 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/pipeline/errors.d.ts +8 -0
- package/dist/pipeline/errors.d.ts.map +1 -1
- package/dist/pipeline/errors.js +25 -16
- package/dist/pipeline/errors.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +17 -9
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +17 -9
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +23 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +42 -0
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/dist/pipeline/steps/authorize.d.ts +6 -5
- package/dist/pipeline/steps/authorize.d.ts.map +1 -1
- package/dist/pipeline/steps/authorize.js +6 -5
- package/dist/pipeline/steps/authorize.js.map +1 -1
- package/dist/pipeline/steps/defaults.d.ts +12 -0
- package/dist/pipeline/steps/defaults.d.ts.map +1 -1
- package/dist/pipeline/steps/defaults.js +42 -7
- package/dist/pipeline/steps/defaults.js.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.d.ts +13 -15
- package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.js +2 -3
- package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
- package/dist/runnerauth/built-in-runner-credential-provider.d.ts +0 -2
- package/dist/runnerauth/built-in-runner-credential-provider.d.ts.map +1 -1
- package/dist/runnerauth/built-in-runner-credential-provider.js +8 -17
- package/dist/runnerauth/built-in-runner-credential-provider.js.map +1 -1
- package/dist/runnerauth/runner-credential-provider.d.ts +17 -7
- package/dist/runnerauth/runner-credential-provider.d.ts.map +1 -1
- package/dist/runnerauth/runner-credential-provider.js.map +1 -1
- package/dist/sandbox/docker.d.ts.map +1 -1
- package/dist/sandbox/docker.js +3 -0
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/kubernetes.d.ts.map +1 -1
- package/dist/sandbox/kubernetes.js +3 -0
- package/dist/sandbox/kubernetes.js.map +1 -1
- package/dist/sandbox/local-process.d.ts.map +1 -1
- package/dist/sandbox/local-process.js +4 -0
- package/dist/sandbox/local-process.js.map +1 -1
- package/dist/sandbox/provisioner.d.ts +18 -6
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/temporal/manager.d.ts +5 -0
- package/dist/temporal/manager.d.ts.map +1 -1
- package/dist/temporal/manager.js +9 -0
- package/dist/temporal/manager.js.map +1 -1
- package/dist/temporal/mcpserver/engine-client.d.ts +2 -2
- package/dist/temporal/mcpserver/engine-client.d.ts.map +1 -1
- package/dist/temporal/mcpserver/engine-client.js +6 -4
- package/dist/temporal/mcpserver/engine-client.js.map +1 -1
- package/dist/temporal/mcpserver/names.d.ts +13 -2
- package/dist/temporal/mcpserver/names.d.ts.map +1 -1
- package/dist/temporal/mcpserver/names.js +15 -2
- package/dist/temporal/mcpserver/names.js.map +1 -1
- package/dist/temporal/sdk-logger.d.ts +74 -0
- package/dist/temporal/sdk-logger.d.ts.map +1 -0
- package/dist/temporal/sdk-logger.js +143 -0
- package/dist/temporal/sdk-logger.js.map +1 -0
- package/package.json +6 -6
- package/src/authorization/README.md +18 -6
- package/src/authorization/__tests__/authorizer.test.ts +5 -1
- package/src/authorization/__tests__/derived-tuples.test.ts +26 -0
- package/src/authorization/__tests__/evaluator.test.ts +4 -0
- package/src/authorization/__tests__/list-read-scope.test.ts +11 -5
- package/src/authorization/__tests__/store-tests.test.ts +3 -1
- package/src/authorization/__tests__/trusted-local-authorizer.test.ts +155 -0
- package/src/authorization/__tests__/unit-owned-kinds.test.ts +420 -0
- package/src/authorization/__tests__/wire-permissions.test.ts +31 -2
- package/src/authorization/authorizer.ts +21 -10
- package/src/authorization/derived-tuples.ts +92 -18
- package/src/authorization/evaluator.ts +30 -15
- package/src/authorization/list-read-scope.ts +4 -0
- package/src/authorization/model/__tests__/registry.test.ts +23 -0
- package/src/authorization/model/data/authorization-model.json +830 -67
- package/src/authorization/model/execution-viewer.ts +32 -27
- package/src/authorization/model/index.ts +4 -1
- package/src/authorization/model/rewrite.ts +5 -3
- package/src/authorization/organization-directory.ts +4 -0
- package/src/authorization/person.ts +32 -1
- package/src/authorization/policy-check.ts +105 -0
- package/src/authorization/posture.ts +45 -4
- package/src/authorization/resource-creators.ts +48 -0
- package/src/authorization/trusted-local-authorizer.ts +91 -0
- package/src/authorization/tuples.ts +17 -0
- package/src/boot/__tests__/compose.test.ts +120 -4
- package/src/boot/__tests__/list-indexes.test.ts +4 -0
- package/src/boot/__tests__/oauth-redirect-uri.test.ts +121 -10
- package/src/boot/__tests__/skill-transfer-origin.test.ts +96 -25
- package/src/boot/compose.ts +153 -61
- package/src/boot/config.ts +28 -12
- package/src/boot/inprocess.ts +18 -4
- package/src/boot/list-indexes.ts +6 -1
- package/src/boot/logger.ts +3 -1
- package/src/boot/oauth-redirect-uri.ts +62 -17
- package/src/boot/skill-transfer-origin.ts +71 -16
- package/src/domain/agent/__tests__/agent.test.ts +42 -1
- package/src/domain/agentchannel/__tests__/agentchannel.test.ts +9 -0
- package/src/domain/agentchannel/__tests__/channel-runtime.test.ts +2 -0
- package/src/domain/agentchannel/__tests__/create-authorization.test.ts +7 -6
- package/src/domain/agentchannel/steps.ts +9 -7
- package/src/domain/agentexecution/__tests__/agentexecution.test.ts +148 -56
- package/src/domain/agentexecution/__tests__/create-steps.test.ts +175 -12
- package/src/domain/agentexecution/__tests__/file-review-seed.ts +91 -0
- package/src/domain/agentexecution/controller.ts +8 -0
- package/src/domain/agentexecution/create-steps.ts +74 -44
- package/src/domain/agentexecution/submit-approval.ts +9 -6
- package/src/domain/agentexecution/submit-file-decision.ts +5 -4
- package/src/domain/agentinstance/__tests__/agentinstance.test.ts +2 -0
- package/src/domain/agentshare/__tests__/agentshare.test.ts +17 -0
- package/src/domain/agentshare/__tests__/create-authorization.test.ts +5 -4
- package/src/domain/agentshare/steps.ts +6 -4
- package/src/domain/apikey/__tests__/verifier.test.ts +73 -1
- package/src/domain/apikey/verifier.ts +45 -1
- package/src/domain/artifact/__tests__/artifact.test.ts +13 -24
- package/src/domain/channelapp/__tests__/channelapp.test.ts +7 -0
- package/src/domain/channelapp/controller.ts +4 -3
- package/src/domain/environment/__tests__/environment.test.ts +13 -0
- package/src/domain/executioncontext/__tests__/executioncontext.test.ts +2 -0
- package/src/domain/executioncontext/steps.ts +2 -1
- package/src/domain/iampolicy/__tests__/access-lists.test.ts +79 -0
- package/src/domain/iampolicy/__tests__/change.test.ts +63 -0
- package/src/domain/iampolicy/__tests__/controller.test.ts +39 -3
- package/src/domain/iampolicy/__tests__/grant-path.test.ts +595 -27
- package/src/domain/iampolicy/__tests__/iampolicy.test.ts +33 -2
- package/src/domain/iampolicy/__tests__/membership.test.ts +47 -5
- package/src/domain/iampolicy/__tests__/resource-store.test.ts +1 -0
- package/src/domain/iampolicy/__tests__/role-lifecycle.test.ts +41 -8
- package/src/domain/iampolicy/__tests__/roles.test.ts +3 -2
- package/src/domain/iampolicy/__tests__/steps.test.ts +75 -6
- package/src/domain/iampolicy/__tests__/support.ts +68 -4
- package/src/domain/iampolicy/access-lists.ts +70 -2
- package/src/domain/iampolicy/change.ts +109 -0
- package/src/domain/iampolicy/constants.ts +8 -0
- package/src/domain/iampolicy/controller.ts +17 -3
- package/src/domain/iampolicy/grant-path.ts +349 -31
- package/src/domain/iampolicy/membership.ts +32 -12
- package/src/domain/iampolicy/resource-store.ts +4 -0
- package/src/domain/iampolicy/role-lifecycle.ts +2 -0
- package/src/domain/iampolicy/roles.ts +8 -0
- package/src/domain/iampolicy/steps.ts +15 -5
- package/src/domain/iampolicy/store-contract.ts +37 -1
- package/src/domain/iampolicy/store.ts +19 -5
- package/src/domain/identityaccount/__tests__/resolve.test.ts +246 -2
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -1
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +20 -5
- package/src/domain/identityaccount/resolve.ts +80 -1
- package/src/domain/identityaccount/resource-store.ts +14 -1
- package/src/domain/identityaccount/steps.ts +4 -3
- package/src/domain/identityaccount/store-contract.ts +4 -4
- package/src/domain/identityaccount/store.ts +6 -1
- package/src/domain/mcpserver/__tests__/connect-authorization.test.ts +1 -0
- package/src/domain/mcpserver/__tests__/connect.test.ts +358 -15
- package/src/domain/mcpserver/__tests__/mcpserver.test.ts +2 -0
- package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +2 -0
- package/src/domain/mcpserver/__tests__/store-faults.test.ts +2 -0
- package/src/domain/mcpserver/connect-sandbox.ts +135 -0
- package/src/domain/mcpserver/connect.ts +226 -56
- package/src/domain/mcpserver/controller.ts +8 -2
- package/src/domain/mcpserver/engine.ts +24 -6
- package/src/domain/mcpserver/start-connect.ts +49 -10
- package/src/domain/memory/__tests__/memory.test.ts +92 -22
- package/src/domain/memory/__tests__/queries.test.ts +173 -0
- package/src/domain/memory/controller.ts +2 -1
- package/src/domain/memory/list-index.ts +32 -0
- package/src/domain/memory/queries.ts +72 -0
- package/src/domain/memory/steps.ts +26 -63
- package/src/domain/oauthapp/__tests__/oauthapp.test.ts +14 -0
- package/src/domain/organization/__tests__/support.ts +41 -0
- package/src/domain/organization/steps.ts +1 -0
- package/src/domain/platformclient/mint.ts +6 -2
- package/src/domain/platformclient/verifier.ts +6 -3
- package/src/domain/plugin/__tests__/plugin.test.ts +11 -24
- package/src/domain/plugin/push.ts +1 -0
- package/src/domain/schedule/__tests__/schedule.composed.test.ts +2 -0
- package/src/domain/schedule/steps.ts +3 -1
- package/src/domain/session/__tests__/session.test.ts +2 -0
- package/src/domain/skill/__tests__/skill.test.ts +7 -25
- package/src/domain/skill/push.ts +1 -0
- package/src/domain/workflow/__tests__/workflow.test.ts +2 -0
- package/src/domain/workflow/registry/data/task-kind-registry.json +27 -1
- package/src/domain/workflowexecution/__tests__/forward-attribution-composed.test.ts +270 -0
- package/src/domain/workflowexecution/__tests__/submit-workflow-task-approval.test.ts +196 -0
- package/src/domain/workflowexecution/__tests__/workflowexecution.test.ts +3 -57
- package/src/domain/workflowexecution/submit-approval.ts +9 -2
- package/src/domain/workflowexecution/submit-file-decision.ts +6 -1
- package/src/domain/workflowexecution/submit-workflow-task-approval.ts +23 -5
- package/src/domain/workflowinstance/controller.ts +27 -9
- package/src/domain/workflowinstance/steps.ts +123 -1
- package/src/extensions/__tests__/apikey-before-sign-in-composed.test.ts +172 -0
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +80 -1
- package/src/extensions/__tests__/composed-services-composed.test.ts +236 -0
- package/src/extensions/__tests__/extension-composition.test.ts +229 -16
- package/src/extensions/__tests__/identity-account-composed.test.ts +84 -4
- package/src/extensions/__tests__/list-read-scope-composed.test.ts +2 -0
- package/src/extensions/__tests__/registry.test.ts +147 -1
- package/src/extensions/__tests__/secret-cleanup-composed.test.ts +2 -0
- package/src/extensions/__tests__/visitor-classifier-points.test.ts +42 -0
- package/src/extensions/composed-services.ts +61 -0
- package/src/extensions/drivers.ts +33 -1
- package/src/extensions/identity.ts +4 -1
- package/src/extensions/registry.ts +105 -0
- package/src/extensions/resource-authorization.ts +87 -0
- package/src/extensions/resource-row-reader.ts +43 -0
- package/src/extensions/visitor-classifier.ts +41 -0
- package/src/identity/__tests__/oidc-verifier.test.ts +38 -12
- package/src/identity/oidc-userinfo.ts +6 -1
- package/src/identity/oidc-verifier.ts +42 -8
- package/src/index.ts +61 -6
- package/src/pipeline/__tests__/steps.test.ts +31 -4
- package/src/pipeline/errors.ts +30 -16
- package/src/pipeline/interceptors/auth.ts +17 -9
- package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +20 -0
- package/src/pipeline/steps/__tests__/guard-memory-capture.test.ts +72 -15
- package/src/pipeline/steps/authorization-tuples.ts +54 -0
- package/src/pipeline/steps/authorize.ts +6 -5
- package/src/pipeline/steps/defaults.ts +52 -7
- package/src/pipeline/steps/guard-memory-capture.ts +15 -20
- package/src/runnerauth/__tests__/built-in-runner-credential-provider.test.ts +1 -1
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +13 -0
- package/src/runnerauth/bound-execution.ts +2 -2
- package/src/runnerauth/built-in-runner-credential-provider.ts +8 -21
- package/src/runnerauth/runner-credential-provider.ts +17 -7
- package/src/sandbox/__tests__/docker.integration.test.ts +4 -0
- package/src/sandbox/__tests__/kubernetes.test.ts +18 -1
- package/src/sandbox/__tests__/local-process.integration.test.ts +4 -0
- package/src/sandbox/__tests__/provisioner.test.ts +1 -0
- package/src/sandbox/docker.ts +3 -0
- package/src/sandbox/kubernetes.ts +3 -0
- package/src/sandbox/local-process.ts +4 -0
- package/src/sandbox/provisioner.ts +18 -6
- package/src/store/postgres/__tests__/support.ts +11 -2
- package/src/temporal/README.md +1 -0
- package/src/temporal/__tests__/manager.test.ts +56 -4
- package/src/temporal/__tests__/sdk-log-workflows.ts +26 -0
- package/src/temporal/__tests__/sdk-logger.e2e.test.ts +150 -0
- package/src/temporal/__tests__/sdk-logger.test.ts +238 -0
- package/src/temporal/manager.ts +9 -0
- package/src/temporal/mcpserver/engine-client.ts +8 -3
- package/src/temporal/mcpserver/names.ts +16 -2
- package/src/temporal/sdk-logger.ts +173 -0
- package/dist/authorization/lane-admission.d.ts +0 -50
- package/dist/authorization/lane-admission.d.ts.map +0 -1
- package/dist/authorization/lane-admission.js +0 -13
- package/dist/authorization/lane-admission.js.map +0 -1
- package/src/authorization/__tests__/lane-admission.test.ts +0 -115
- package/src/authorization/lane-admission.ts +0 -73
|
@@ -64,6 +64,7 @@ import type {
|
|
|
64
64
|
AuthzDecision,
|
|
65
65
|
} from "../extensions/authorizer.js";
|
|
66
66
|
import type { CallerIdentity } from "../extensions/identity.js";
|
|
67
|
+
import type { ResourceRowReader } from "../extensions/resource-row-reader.js";
|
|
67
68
|
import {
|
|
68
69
|
kindEnumName,
|
|
69
70
|
kindServedByEdition,
|
|
@@ -81,15 +82,18 @@ import { formatObjectRef } from "./tuples.js";
|
|
|
81
82
|
/**
|
|
82
83
|
* Kinds whose missing row is a denial, never `not-found` (arm 4): the
|
|
83
84
|
* cloud's `PROBE_EXEMPT_KINDS` (stigmer-cloud
|
|
84
|
-
* src/authorizer/fga-authorizer.ts)
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
85
|
+
* src/authorizer/fga-authorizer.ts), the same set. The cloud exempts them
|
|
86
|
+
* because their rows live in its own tables, out of its probe's reach;
|
|
87
|
+
* matching the set here keeps the wire identical across editions (an
|
|
88
|
+
* unknown platform client's id is PERMISSION_DENIED with the annotation's
|
|
89
|
+
* copy in both), so a member cannot learn which provider, invitation or
|
|
90
|
+
* team ids exist in an organization they may not read. In open source,
|
|
91
|
+
* `platform`, `identity_provider`, `invitation` and `team` are refused by
|
|
92
|
+
* arm 2 before any row is asked about, so their entries matter only to an
|
|
93
|
+
* edition that serves them. `platform` also has no row at all
|
|
94
|
+
* (model/bindings.ts, ROWLESS): outside this set every check on it would
|
|
95
|
+
* answer not-found without evaluating. The cloud pins every kind here
|
|
96
|
+
* inside its own `PROBE_EXEMPT_KINDS`, which is why this set is exported.
|
|
93
97
|
*
|
|
94
98
|
* `iam_policy` is reachable as a target through the IamPolicy RPCs' own
|
|
95
99
|
* `resource.kind` (a caller may name it); the grant scope refuses such a
|
|
@@ -97,9 +101,13 @@ import { formatObjectRef } from "./tuples.js";
|
|
|
97
101
|
* keeps the wire the same on the way there.
|
|
98
102
|
*/
|
|
99
103
|
export const NOT_FOUND_EXEMPT_KINDS: ReadonlySet<ApiResourceKind> = new Set([
|
|
104
|
+
ApiResourceKind.platform,
|
|
100
105
|
ApiResourceKind.identity_account,
|
|
106
|
+
ApiResourceKind.identity_provider,
|
|
101
107
|
ApiResourceKind.iam_policy,
|
|
102
108
|
ApiResourceKind.platform_client,
|
|
109
|
+
ApiResourceKind.invitation,
|
|
110
|
+
ApiResourceKind.team,
|
|
103
111
|
]);
|
|
104
112
|
|
|
105
113
|
/** The Java RequestAuthorizationService's pre-check copy, byte for byte (the cloud renders the same). */
|
|
@@ -121,9 +129,11 @@ export interface BuiltInAuthorizerDeps {
|
|
|
121
129
|
readonly policies: IamPolicyStore;
|
|
122
130
|
/** The account port: the caller's account, and identity_account targets. */
|
|
123
131
|
readonly accounts: AccountsByCaller;
|
|
124
|
-
/** The served edition (`extensions.edition`);
|
|
132
|
+
/** The served edition (`extensions.edition`); above `oss`, boot has checked every served kind's rows are readable. */
|
|
125
133
|
readonly edition: ServerEdition;
|
|
126
134
|
readonly logger: Logger;
|
|
135
|
+
/** The readers of the kinds units keep themselves (`drivers.resourceRowReaders`), handed to every tuple source. */
|
|
136
|
+
readonly rowReaders?: ReadonlyMap<ApiResourceKind, ResourceRowReader>;
|
|
127
137
|
/** The declarations to evaluate; the built-in model unless a test says otherwise. */
|
|
128
138
|
readonly model?: Model;
|
|
129
139
|
}
|
|
@@ -163,6 +173,7 @@ export function newBuiltInAuthorizer(deps: BuiltInAuthorizerDeps): Authorizer {
|
|
|
163
173
|
store: deps.store,
|
|
164
174
|
policies: deps.policies,
|
|
165
175
|
accounts: deps.accounts,
|
|
176
|
+
rowReaders: deps.rowReaders,
|
|
166
177
|
model,
|
|
167
178
|
},
|
|
168
179
|
person,
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
* organization`), so a person who left the organization reads the
|
|
46
46
|
* team's rows and is admitted by none of them.
|
|
47
47
|
*
|
|
48
|
+
* A check about an object rather than a person (an organization asked
|
|
49
|
+
* whether a resource is its own, authorization/policy-check.ts) reads the
|
|
50
|
+
* rows that name that object directly, and holds no team.
|
|
51
|
+
*
|
|
48
52
|
* Open source serves no team (the kind's tier is enterprise), so the
|
|
49
53
|
* person's rows name none and the second read never happens: one read per
|
|
50
54
|
* source, an indexed read on the OSS adapter (its list index by
|
|
@@ -71,15 +75,19 @@
|
|
|
71
75
|
* spec fields the facts do not carry), so listing the two instance kinds
|
|
72
76
|
* costs one row read per candidate, stated in the scope's cost pins.
|
|
73
77
|
*
|
|
74
|
-
*
|
|
75
|
-
* `identity_account` object is read
|
|
76
|
-
* (`accounts.findById`), the binding every other
|
|
77
|
-
* the verifiers, whoAmI, the create path — follows
|
|
78
|
-
* registers its own account store and keeps the
|
|
79
|
-
* therefore still lets a person read their own
|
|
80
|
-
* is `owner@self`)
|
|
81
|
-
* row.
|
|
82
|
-
*
|
|
78
|
+
* A row is read where the composition keeps it. Open source's kinds are
|
|
79
|
+
* read through the generic Store. An `identity_account` object is read
|
|
80
|
+
* through the account PORT (`accounts.findById`), the binding every other
|
|
81
|
+
* reader of accounts — the verifiers, whoAmI, the create path — follows:
|
|
82
|
+
* a composition that registers its own account store and keeps the
|
|
83
|
+
* built-in authorizer therefore still lets a person read their own
|
|
84
|
+
* account (the derivation is `owner@self`), where a generic read would
|
|
85
|
+
* miss and deny them their own row. A kind a unit keeps in a store of its
|
|
86
|
+
* own (an identity provider, an invitation, a team, in the editions that
|
|
87
|
+
* serve them) is read through the reader the unit registered for it
|
|
88
|
+
* (`rowReaders`, extensions/resource-row-reader.ts), so a team a grant
|
|
89
|
+
* names resolves its organization from the row its unit wrote. IamPolicy
|
|
90
|
+
* rows are already the port's (`findByPrincipal`), so they need no reader.
|
|
83
91
|
*/
|
|
84
92
|
import type { Message } from "@bufbuild/protobuf";
|
|
85
93
|
|
|
@@ -91,6 +99,7 @@ import { isPersonStamp } from "../domain/iampolicy/membership.js";
|
|
|
91
99
|
import type { IamPolicyStore } from "../domain/iampolicy/store.js";
|
|
92
100
|
import type { IdentityAccountStore } from "../domain/identityaccount/store.js";
|
|
93
101
|
import type { VisibilityTupleShape } from "../extensions/resource-authorization.js";
|
|
102
|
+
import type { ResourceRowReader } from "../extensions/resource-row-reader.js";
|
|
94
103
|
import {
|
|
95
104
|
getKindMeta,
|
|
96
105
|
kindByEnumName,
|
|
@@ -105,13 +114,13 @@ import type { Model } from "./model/index.js";
|
|
|
105
114
|
import { builtInModel } from "./model/index.js";
|
|
106
115
|
import type {
|
|
107
116
|
ObjectRef,
|
|
108
|
-
|
|
117
|
+
Principal,
|
|
109
118
|
RowLoader,
|
|
110
119
|
Subject,
|
|
111
120
|
Tuple,
|
|
112
121
|
TupleSource,
|
|
113
122
|
} from "./tuples.js";
|
|
114
|
-
import { ACCOUNT_TYPE, formatObjectRef } from "./tuples.js";
|
|
123
|
+
import { ACCOUNT_TYPE, formatObjectRef, isPerson } from "./tuples.js";
|
|
115
124
|
|
|
116
125
|
/**
|
|
117
126
|
* Kinds whose `[identity_account]` owner is recorded as an IamPolicy row
|
|
@@ -123,6 +132,10 @@ export const ROW_RECORDED_OWNER_KINDS: ReadonlySet<ApiResourceKind> = new Set([
|
|
|
123
132
|
ApiResourceKind.organization,
|
|
124
133
|
]);
|
|
125
134
|
|
|
135
|
+
/** The organization type, and the relation that stands while a person holds a role on it (tenancy/organization.fga). */
|
|
136
|
+
const ORGANIZATION_TYPE = kindEnumName(ApiResourceKind.organization);
|
|
137
|
+
const AFFILIATED_RELATION = "affiliated";
|
|
138
|
+
|
|
126
139
|
/** The FGA type a team grant names, and the relation that makes a person one of its members (the model's `team#member`). */
|
|
127
140
|
const TEAM_TYPE = kindEnumName(ApiResourceKind.team);
|
|
128
141
|
const TEAM_MEMBER_RELATION = "member";
|
|
@@ -223,6 +236,8 @@ export interface DerivedTupleSourceDeps {
|
|
|
223
236
|
readonly policies: IamPolicyStore;
|
|
224
237
|
/** The account port — an `identity_account` object is read through it, never the generic Store (the module header). */
|
|
225
238
|
readonly accounts: Pick<IdentityAccountStore, "findById">;
|
|
239
|
+
/** The readers of the kinds units keep themselves (`drivers.resourceRowReaders`); absent, every other row is the generic Store's. */
|
|
240
|
+
readonly rowReaders?: ReadonlyMap<ApiResourceKind, ResourceRowReader>;
|
|
226
241
|
/** The declarations to derive with; the built-in model unless a test says otherwise. */
|
|
227
242
|
readonly model?: Model;
|
|
228
243
|
}
|
|
@@ -231,7 +246,8 @@ export interface DerivedTupleSource extends TupleSource {
|
|
|
231
246
|
/** The memoised row reads, exposed for a declaration's `derived` rules and for tests. */
|
|
232
247
|
readonly loader: RowLoader;
|
|
233
248
|
/**
|
|
234
|
-
* The person's own IamPolicy rows as tuples
|
|
249
|
+
* The person's own IamPolicy rows as tuples, each organization role with
|
|
250
|
+
* the organization's `affiliated` tuple it stands for — the ONE read of them this
|
|
235
251
|
* source makes, shared with `tuplesOf`. A list-shaped consumer (the
|
|
236
252
|
* organization directory; the list scope) reads its candidate objects
|
|
237
253
|
* from here instead of scanning the port a second time. The rows granted
|
|
@@ -248,7 +264,7 @@ export interface DerivedTupleSourceSeed {
|
|
|
248
264
|
|
|
249
265
|
export function newDerivedTupleSource(
|
|
250
266
|
deps: DerivedTupleSourceDeps,
|
|
251
|
-
|
|
267
|
+
principal: Principal,
|
|
252
268
|
seed?: DerivedTupleSourceSeed,
|
|
253
269
|
): DerivedTupleSource {
|
|
254
270
|
const model = deps.model ?? builtInModel;
|
|
@@ -307,9 +323,13 @@ export function newDerivedTupleSource(
|
|
|
307
323
|
|
|
308
324
|
function rowTuples(): Promise<ReadonlyArray<Tuple>> {
|
|
309
325
|
if (personRows === undefined) {
|
|
310
|
-
personRows =
|
|
311
|
-
|
|
312
|
-
|
|
326
|
+
personRows = isPerson(principal)
|
|
327
|
+
? deps.policies
|
|
328
|
+
.findByPrincipal(ACCOUNT_TYPE, principal.accountId)
|
|
329
|
+
.then((found) => found.flatMap(tuplesOfPersonRow))
|
|
330
|
+
: deps.policies
|
|
331
|
+
.findByPrincipal(principal.object.type, principal.object.id)
|
|
332
|
+
.then((found) => found.filter(isDirectGrant).map(tupleOfRow));
|
|
313
333
|
}
|
|
314
334
|
return personRows;
|
|
315
335
|
}
|
|
@@ -357,7 +377,10 @@ export function newDerivedTupleSource(
|
|
|
357
377
|
const fromRows =
|
|
358
378
|
(await reachableTuples()).get(pairKey(object, relation)) ?? [];
|
|
359
379
|
const declaration = model.byType(object.type);
|
|
360
|
-
if (declaration === undefined) {
|
|
380
|
+
if (declaration === undefined || isAffiliation(object, relation)) {
|
|
381
|
+
// An organization's `affiliated` tuples are the person's rows'
|
|
382
|
+
// (tuplesOfPersonRow); the organization's own row derives none, so
|
|
383
|
+
// it is not read for them.
|
|
361
384
|
return fromRows;
|
|
362
385
|
}
|
|
363
386
|
const fromRow = (await derivedTuplesOf(object)).filter(onPair);
|
|
@@ -378,7 +401,7 @@ export function newDerivedTupleSource(
|
|
|
378
401
|
* the row does not exist.
|
|
379
402
|
*/
|
|
380
403
|
async function loadRow(
|
|
381
|
-
deps: Pick<DerivedTupleSourceDeps, "store" | "accounts">,
|
|
404
|
+
deps: Pick<DerivedTupleSourceDeps, "store" | "accounts" | "rowReaders">,
|
|
382
405
|
model: Model,
|
|
383
406
|
object: ObjectRef,
|
|
384
407
|
): Promise<Message | undefined> {
|
|
@@ -395,6 +418,10 @@ async function loadRow(
|
|
|
395
418
|
if (kind === ApiResourceKind.identity_account) {
|
|
396
419
|
return deps.accounts.findById(object.id);
|
|
397
420
|
}
|
|
421
|
+
const reader = deps.rowReaders?.get(kind);
|
|
422
|
+
if (reader !== undefined) {
|
|
423
|
+
return reader.findById(object.id);
|
|
424
|
+
}
|
|
398
425
|
try {
|
|
399
426
|
return await deps.store.getResource(kind, object.id, declaration.schema);
|
|
400
427
|
} catch (error) {
|
|
@@ -405,6 +432,15 @@ async function loadRow(
|
|
|
405
432
|
}
|
|
406
433
|
}
|
|
407
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Whether a row names its principal directly (`organization:o`), not as a
|
|
437
|
+
* userset (`organization:o#member`): the rows an object principal itself
|
|
438
|
+
* holds. A userset row grants the object's members, never the object.
|
|
439
|
+
*/
|
|
440
|
+
function isDirectGrant(row: IamPolicy): boolean {
|
|
441
|
+
return (row.spec?.principal?.relation ?? "") === "";
|
|
442
|
+
}
|
|
443
|
+
|
|
408
444
|
/** The key a tuple is served under: its object and relation. */
|
|
409
445
|
function pairKey(object: ObjectRef, relation: string): string {
|
|
410
446
|
return `${formatObjectRef(object)}#${relation}`;
|
|
@@ -426,6 +462,44 @@ function indexByPair(
|
|
|
426
462
|
return index;
|
|
427
463
|
}
|
|
428
464
|
|
|
465
|
+
/** Whether the pair is an organization's `affiliated`, which only the person's rows carry. */
|
|
466
|
+
function isAffiliation(object: ObjectRef, relation: string): boolean {
|
|
467
|
+
return object.type === ORGANIZATION_TYPE && relation === AFFILIATED_RELATION;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* A row of the person's as the tuples it stands for: the tuple it records,
|
|
472
|
+
* and, for a role on an organization, the organization's `affiliated`
|
|
473
|
+
* tuple. `affiliated` is stored in the model so its bound costs one read
|
|
474
|
+
* (fga/model/tenancy/organization.fga); it stands exactly while the person
|
|
475
|
+
* holds a row on the organization, and this edition derives it from those
|
|
476
|
+
* rows here, in the same one read, where an edition that stores tuples
|
|
477
|
+
* writes it from the grant path's affiliation announcements. A row that
|
|
478
|
+
* names a userset (a team's members) is not the person's role and stands
|
|
479
|
+
* for no affiliation.
|
|
480
|
+
*/
|
|
481
|
+
function tuplesOfPersonRow(row: IamPolicy): ReadonlyArray<Tuple> {
|
|
482
|
+
const recorded = tupleOfRow(row);
|
|
483
|
+
const principal = row.spec?.principal;
|
|
484
|
+
if (
|
|
485
|
+
recorded.object.type !== ORGANIZATION_TYPE ||
|
|
486
|
+
recorded.object.id === "" ||
|
|
487
|
+
principal === undefined ||
|
|
488
|
+
principal.kind !== ACCOUNT_TYPE ||
|
|
489
|
+
principal.relation !== ""
|
|
490
|
+
) {
|
|
491
|
+
return [recorded];
|
|
492
|
+
}
|
|
493
|
+
return [
|
|
494
|
+
recorded,
|
|
495
|
+
{
|
|
496
|
+
object: recorded.object,
|
|
497
|
+
relation: AFFILIATED_RELATION,
|
|
498
|
+
subject: account(principal.id),
|
|
499
|
+
},
|
|
500
|
+
];
|
|
501
|
+
}
|
|
502
|
+
|
|
429
503
|
/** An IamPolicy row as the tuple it records: `resource#relation@principal`. */
|
|
430
504
|
function tupleOfRow(row: IamPolicy): Tuple {
|
|
431
505
|
const spec = row.spec;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The evaluator — OpenFGA's check, over the built-in model and a tuple
|
|
3
3
|
* source, small because the model uses five rewrite forms and nothing
|
|
4
|
-
* else (model/rewrite.ts). `checkRelation(object, relation,
|
|
5
|
-
* answers "does this person hold this relation on this
|
|
6
|
-
* the cloud's engine answers it over stored tuples, so the
|
|
7
|
-
* share one meaning of authorization.
|
|
4
|
+
* else (model/rewrite.ts). `checkRelation(object, relation, principal)`
|
|
5
|
+
* answers "does this person (or this object) hold this relation on this
|
|
6
|
+
* object" the way the cloud's engine answers it over stored tuples, so the
|
|
7
|
+
* two editions share one meaning of authorization. The principal is
|
|
8
|
+
* almost always a person; an object principal (an organization) is how a
|
|
9
|
+
* unit asks the structural questions the cloud asks its engine, such as
|
|
10
|
+
* whether a resource belongs to an organization. There is no context parameter: the
|
|
8
11
|
* model declares no condition, so a check has no posture to state.
|
|
9
12
|
*
|
|
10
13
|
* The walk, in the order a `.fga` line reads:
|
|
@@ -12,7 +15,8 @@
|
|
|
12
15
|
* its subject's TYPE is in the line's restriction list — the check
|
|
13
16
|
* OpenFGA makes at write time, made here at read time, so a derived
|
|
14
17
|
* tuple the model no longer admits denies instead of allowing. An
|
|
15
|
-
* object subject matches when it
|
|
18
|
+
* object subject matches a person when it is an account naming one of
|
|
19
|
+
* their aliases, and an object principal when it is that very object;
|
|
16
20
|
* a userset subject is resolved on its own object.
|
|
17
21
|
* - `computed`: the same object, another relation.
|
|
18
22
|
* - `from`: every object the tupleset relation links to (again within
|
|
@@ -46,8 +50,8 @@
|
|
|
46
50
|
*/
|
|
47
51
|
import type { Model } from "./model/index.js";
|
|
48
52
|
import type { Rewrite, SubjectType } from "./model/rewrite.js";
|
|
49
|
-
import type { ObjectRef,
|
|
50
|
-
import { ACCOUNT_TYPE, formatObjectRef, pairKey } from "./tuples.js";
|
|
53
|
+
import type { ObjectRef, Principal, Subject, TupleSource } from "./tuples.js";
|
|
54
|
+
import { ACCOUNT_TYPE, formatObjectRef, isPerson, pairKey } from "./tuples.js";
|
|
51
55
|
|
|
52
56
|
/**
|
|
53
57
|
* OpenFGA's default resolution-depth limit (its `resolveNodeLimit`), so
|
|
@@ -88,7 +92,7 @@ export async function checkRelation(
|
|
|
88
92
|
deps: EvaluationDeps,
|
|
89
93
|
object: ObjectRef,
|
|
90
94
|
relation: string,
|
|
91
|
-
|
|
95
|
+
principal: Principal,
|
|
92
96
|
): Promise<boolean> {
|
|
93
97
|
if (deps.model.byType(object.type) === undefined) {
|
|
94
98
|
throw new AuthorizationEvaluationError(
|
|
@@ -96,7 +100,7 @@ export async function checkRelation(
|
|
|
96
100
|
`no declaration for kind '${object.type}' (target ${formatObjectRef(object)})`,
|
|
97
101
|
);
|
|
98
102
|
}
|
|
99
|
-
return new Walk(deps,
|
|
103
|
+
return new Walk(deps, principal).resolve(object, relation, 0);
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
/** One check's state: the memo and the in-progress set, over one source. */
|
|
@@ -106,7 +110,7 @@ class Walk {
|
|
|
106
110
|
|
|
107
111
|
constructor(
|
|
108
112
|
private readonly deps: EvaluationDeps,
|
|
109
|
-
private readonly
|
|
113
|
+
private readonly principal: Principal,
|
|
110
114
|
) {}
|
|
111
115
|
|
|
112
116
|
resolve(
|
|
@@ -203,7 +207,7 @@ class Walk {
|
|
|
203
207
|
}
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
/** Whether one direct tuple's subject reaches the
|
|
210
|
+
/** Whether one direct tuple's subject reaches the principal, within the line's type restriction. */
|
|
207
211
|
private async subjectHolds(
|
|
208
212
|
subject: Subject,
|
|
209
213
|
restriction: ReadonlyArray<SubjectType>,
|
|
@@ -212,12 +216,10 @@ class Walk {
|
|
|
212
216
|
switch (subject.form) {
|
|
213
217
|
case "object":
|
|
214
218
|
return (
|
|
215
|
-
subject.object.type === ACCOUNT_TYPE &&
|
|
216
219
|
restriction.some(
|
|
217
220
|
(allowed) =>
|
|
218
|
-
allowed.form === "object" && allowed.type ===
|
|
219
|
-
) &&
|
|
220
|
-
this.person.aliases.has(subject.object.id)
|
|
221
|
+
allowed.form === "object" && allowed.type === subject.object.type,
|
|
222
|
+
) && this.isPrincipal(subject.object)
|
|
221
223
|
);
|
|
222
224
|
case "userset":
|
|
223
225
|
return (
|
|
@@ -235,6 +237,19 @@ class Walk {
|
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
|
|
240
|
+
/** Whether an object subject names the principal: one of a person's aliases on an account, or the object principal itself. */
|
|
241
|
+
private isPrincipal(object: ObjectRef): boolean {
|
|
242
|
+
if (isPerson(this.principal)) {
|
|
243
|
+
return (
|
|
244
|
+
object.type === ACCOUNT_TYPE && this.principal.aliases.has(object.id)
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return (
|
|
248
|
+
object.type === this.principal.object.type &&
|
|
249
|
+
object.id === this.principal.object.id
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
238
253
|
/** The object types the tupleset line admits — `[organization]`, `[session]` — from its `this` nodes. */
|
|
239
254
|
private objectTypesOf(
|
|
240
255
|
object: ObjectRef,
|
|
@@ -70,6 +70,7 @@ import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apireso
|
|
|
70
70
|
import type { Logger } from "../boot/logger.js";
|
|
71
71
|
import type { IamPolicyStore } from "../domain/iampolicy/store.js";
|
|
72
72
|
import type { CallerIdentity } from "../extensions/identity.js";
|
|
73
|
+
import type { ResourceRowReader } from "../extensions/resource-row-reader.js";
|
|
73
74
|
import type {
|
|
74
75
|
ListEntryMeta,
|
|
75
76
|
ListReadScope,
|
|
@@ -101,6 +102,8 @@ export interface BuiltInListReadScopeDeps {
|
|
|
101
102
|
/** The account port: the caller's account, and the parent hops that land on one. */
|
|
102
103
|
readonly accounts: AccountsByCaller;
|
|
103
104
|
readonly logger: Logger;
|
|
105
|
+
/** The readers of the kinds units keep themselves (`drivers.resourceRowReaders`), handed to every tuple source. */
|
|
106
|
+
readonly rowReaders?: ReadonlyMap<ApiResourceKind, ResourceRowReader>;
|
|
104
107
|
/** The declarations to evaluate; the built-in model unless a test says otherwise. */
|
|
105
108
|
readonly model?: Model;
|
|
106
109
|
}
|
|
@@ -126,6 +129,7 @@ export function newBuiltInListReadScope(
|
|
|
126
129
|
store: deps.store,
|
|
127
130
|
policies: deps.policies,
|
|
128
131
|
accounts: deps.accounts,
|
|
132
|
+
rowReaders: deps.rowReaders,
|
|
129
133
|
model,
|
|
130
134
|
},
|
|
131
135
|
person,
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* exactly the four kinds the wider editions serve, so a kind the
|
|
12
12
|
* contract moves between tiers is a visible diff here;
|
|
13
13
|
* - a kind is reached by enum and by FGA type name alike;
|
|
14
|
+
* - every role a kind's `grantable_roles` lets a person hold is a
|
|
15
|
+
* relation of the kind's type whose direct list admits
|
|
16
|
+
* `identity_account`, so a grant the step accepts is a tuple the engine
|
|
17
|
+
* can store (`authorization_config.proto` states the rule; this holds
|
|
18
|
+
* the model to it);
|
|
14
19
|
* - the relations whose direct list admits a team (`team#member`) are
|
|
15
20
|
* exactly the roles the kind's `team_grantable_roles` names, a subset
|
|
16
21
|
* of what a person can be granted and never ownership, so the grant
|
|
@@ -283,6 +288,10 @@ function inheritedWholeKinds(): ReadonlyArray<{
|
|
|
283
288
|
});
|
|
284
289
|
}
|
|
285
290
|
|
|
291
|
+
function isPerson(subject: SubjectType): boolean {
|
|
292
|
+
return subject.form === "object" && subject.type === "identity_account";
|
|
293
|
+
}
|
|
294
|
+
|
|
286
295
|
function isTeamMembers(subject: SubjectType): boolean {
|
|
287
296
|
return subject.form === "userset" && subject.type === "team" && subject.relation === "member";
|
|
288
297
|
}
|
|
@@ -371,6 +380,20 @@ describe("the built-in model", () => {
|
|
|
371
380
|
}
|
|
372
381
|
});
|
|
373
382
|
|
|
383
|
+
it("stores every role a kind lets a person hold as a relation that admits the person directly — the model and the contract say one thing", () => {
|
|
384
|
+
const gaps: string[] = [];
|
|
385
|
+
for (const declaration of builtInModel.declarations) {
|
|
386
|
+
for (const role of grantableRolesFor(declaration.kind)) {
|
|
387
|
+
const relation = IamRole[role];
|
|
388
|
+
const rewrite = declaration.relations.get(relation);
|
|
389
|
+
if (rewrite === undefined || !directSubjects(rewrite).some(isPerson)) {
|
|
390
|
+
gaps.push(`${declaration.type}#${relation}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
expect(gaps.sort()).toEqual([]);
|
|
395
|
+
});
|
|
396
|
+
|
|
374
397
|
it("lets a team hold only roles a person can hold on the kind, and never ownership", () => {
|
|
375
398
|
for (const value of ApiResourceKindSchema.values) {
|
|
376
399
|
const kind = value.number as ApiResourceKind;
|