@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
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* on the in-process transport (the `internal` class);
|
|
21
21
|
* - checkMyPermission's three arms: an enterprise-tiered kind is false
|
|
22
22
|
* with the Authorizer never consulted (the settings navigation stays
|
|
23
|
-
* hidden); can_grant_access outside the scope is false
|
|
23
|
+
* hidden); can_grant_access outside the scope is false, while
|
|
24
|
+
* can_manage_audience is the Authorizer's answer on every kind; an
|
|
24
25
|
* organization permission is the composed Authorizer's answer; an
|
|
25
26
|
* unknown permission is INVALID_ARGUMENT;
|
|
26
27
|
* - the tuple-half queries are UNIMPLEMENTED with the edition named;
|
|
@@ -65,6 +66,7 @@ import {
|
|
|
65
66
|
roleNotGrantableMessage,
|
|
66
67
|
unknownPermissionMessage,
|
|
67
68
|
} from "../constants.js";
|
|
69
|
+
import { seedOrganizations } from "../../organization/__tests__/support.js";
|
|
68
70
|
import { orgRole, triple } from "./support.js";
|
|
69
71
|
|
|
70
72
|
const OPERATOR_EMAIL = "operator@example.com";
|
|
@@ -115,6 +117,7 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
|
|
|
115
117
|
});
|
|
116
118
|
const port = await server.start();
|
|
117
119
|
transport = createGrpcTransport({ baseUrl: `http://127.0.0.1:${port}` });
|
|
120
|
+
await seedOrganizations(transport, ["acme"]);
|
|
118
121
|
command = createClient(IamPolicyCommandController, transport);
|
|
119
122
|
query = createClient(IamPolicyQueryController, transport);
|
|
120
123
|
organizations = createClient(OrganizationCommandController, transport);
|
|
@@ -191,7 +194,21 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
|
|
|
191
194
|
it("deleting the organization cleans its rows", async () => {
|
|
192
195
|
const org = await newOrganization();
|
|
193
196
|
await organizations.delete({ value: org });
|
|
194
|
-
|
|
197
|
+
// The wire now refuses a count of an Organization that is gone
|
|
198
|
+
// (stigmer#1163), so the rows are counted by the server itself: the
|
|
199
|
+
// in-process caller skips authorization.
|
|
200
|
+
const wire = await grpcError(() =>
|
|
201
|
+
query.getPrincipalsCount({
|
|
202
|
+
orgId: org,
|
|
203
|
+
principalKind: "identity_account",
|
|
204
|
+
}),
|
|
205
|
+
);
|
|
206
|
+
expect(wire.code).toBe(Code.NotFound);
|
|
207
|
+
expect(wire.rawMessage).toBe(`Organization not found: ${org}`);
|
|
208
|
+
const count = await createClient(
|
|
209
|
+
IamPolicyQueryController,
|
|
210
|
+
server.inProcessTransport,
|
|
211
|
+
).getPrincipalsCount({
|
|
195
212
|
orgId: org,
|
|
196
213
|
principalKind: "identity_account",
|
|
197
214
|
});
|
|
@@ -468,6 +485,20 @@ describe("iampolicy domain (composed server, trusted-local posture)", () => {
|
|
|
468
485
|
expect(viewAgent.isAuthorized).toBe(true);
|
|
469
486
|
});
|
|
470
487
|
|
|
488
|
+
it("can_manage_audience is the Authorizer's answer on every kind, where can_grant_access is false outside the scope — the console's audience controls stay the owner's on open source (stigmer#1495)", async () => {
|
|
489
|
+
for (const [kind, id] of [
|
|
490
|
+
["agent", "agt_01hzzzzzzzzzzzzzzzzzzzzzzz"],
|
|
491
|
+
["workflow_instance", "win_01hzzzzzzzzzzzzzzzzzzzzzzz"],
|
|
492
|
+
] as const) {
|
|
493
|
+
const resource = create(ApiResourceRefSchema, { kind, id });
|
|
494
|
+
const audience = await query.checkMyPermission({ resource, relation: "can_manage_audience" });
|
|
495
|
+
const grant = await query.checkMyPermission({ resource, relation: "can_grant_access" });
|
|
496
|
+
// The permissive single-team Authorizer allows everything it is asked.
|
|
497
|
+
expect(audience.isAuthorized, kind).toBe(true);
|
|
498
|
+
expect(grant.isAuthorized, kind).toBe(false);
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
|
|
471
502
|
it("an unknown permission is INVALID_ARGUMENT, quoted", async () => {
|
|
472
503
|
const error = await grpcError(() =>
|
|
473
504
|
query.checkMyPermission({
|
|
@@ -21,7 +21,11 @@
|
|
|
21
21
|
* - `member` otherwise;
|
|
22
22
|
* - nothing for a non-`user` caller class; nothing on an organization
|
|
23
23
|
* the account already holds a row on (idempotent by construction), so
|
|
24
|
-
* a run that faulted midway converges on the next
|
|
24
|
+
* a run that faulted midway converges on the next;
|
|
25
|
+
* - nothing, in the reconciliation, for a federated account, whose
|
|
26
|
+
* subject and email its identity provider chose: one asserting a
|
|
27
|
+
* founder's subject and the operator's email earns neither `owner`
|
|
28
|
+
* nor `admin`, nor `member` anywhere.
|
|
25
29
|
*
|
|
26
30
|
* ensureOperatorOwnership(operator): `owner` on every organization that
|
|
27
31
|
* has NO owner row (Q-S4-3: a boot-time write never overrides a recorded
|
|
@@ -60,6 +64,7 @@ import { TimestampSchema } from "@bufbuild/protobuf/wkt";
|
|
|
60
64
|
import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
|
|
61
65
|
import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
62
66
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
67
|
+
import { ApiResourceReferenceSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
63
68
|
import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
64
69
|
import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
65
70
|
import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
|
|
@@ -81,7 +86,7 @@ import {
|
|
|
81
86
|
} from "../membership.js";
|
|
82
87
|
import type { MembershipRules, ScannedResource } from "../membership.js";
|
|
83
88
|
import type { IamPolicyStore } from "../store.js";
|
|
84
|
-
import { fakeIamPolicyStore } from "./support.js";
|
|
89
|
+
import { NO_RECORDED_CREATORS, fakeIamPolicyStore } from "./support.js";
|
|
85
90
|
import type { FakeIamPolicyStore } from "./support.js";
|
|
86
91
|
|
|
87
92
|
const OPERATOR_EMAIL = "operator@example.com";
|
|
@@ -124,6 +129,7 @@ describe("membership rules", () => {
|
|
|
124
129
|
): MembershipRules {
|
|
125
130
|
return newMembershipRules({
|
|
126
131
|
grantPath: newIamPolicyGrantPath({
|
|
132
|
+
creators: NO_RECORDED_CREATORS,
|
|
127
133
|
policies: port,
|
|
128
134
|
lifecycle: undefined,
|
|
129
135
|
logger: silentLogger,
|
|
@@ -139,6 +145,7 @@ describe("membership rules", () => {
|
|
|
139
145
|
store = temp.store;
|
|
140
146
|
policies = fakeIamPolicyStore();
|
|
141
147
|
grantPath = newIamPolicyGrantPath({
|
|
148
|
+
creators: NO_RECORDED_CREATORS,
|
|
142
149
|
policies,
|
|
143
150
|
lifecycle: undefined,
|
|
144
151
|
logger: silentLogger,
|
|
@@ -242,10 +249,18 @@ describe("membership rules", () => {
|
|
|
242
249
|
sub: string,
|
|
243
250
|
email: string,
|
|
244
251
|
createdAtSeconds: number,
|
|
245
|
-
overrides: { isMachineAccount?: boolean } = {},
|
|
252
|
+
overrides: { isMachineAccount?: boolean; federated?: boolean } = {},
|
|
246
253
|
): Promise<IdentityAccount> {
|
|
247
254
|
const row = account(sub, email);
|
|
248
255
|
row.spec!.isMachineAccount = overrides.isMachineAccount ?? false;
|
|
256
|
+
if (overrides.federated === true) {
|
|
257
|
+
row.spec!.provisioningMode = IdentityAccountProvisioningMode.federated;
|
|
258
|
+
row.spec!.identityProviderRef = create(ApiResourceReferenceSchema, {
|
|
259
|
+
org: "acme",
|
|
260
|
+
kind: ApiResourceKind.identity_provider,
|
|
261
|
+
slug: "acme-okta",
|
|
262
|
+
});
|
|
263
|
+
}
|
|
249
264
|
row.status = create(IdentityAccountSchema, {
|
|
250
265
|
status: {
|
|
251
266
|
audit: {
|
|
@@ -321,7 +336,11 @@ describe("membership rules", () => {
|
|
|
321
336
|
const alice = account("auth0|alice", "alice@example.com");
|
|
322
337
|
await rules.onAccountCreated(alice, userCaller(alice.metadata!.id));
|
|
323
338
|
// The organization was bootstrapped; its owner is then revoked.
|
|
324
|
-
await grantPath.revokeOrgAccess(
|
|
339
|
+
await grantPath.revokeOrgAccess(
|
|
340
|
+
alice.metadata!.id,
|
|
341
|
+
"acme",
|
|
342
|
+
userCaller(alice.metadata!.id),
|
|
343
|
+
);
|
|
325
344
|
expect(policies.rows.size).toBe(0);
|
|
326
345
|
// A second creator stamp keeps the "no other person created anything here" arm from firing on its own.
|
|
327
346
|
await seedAgent("agt_alice", "acme", alice.metadata!.id);
|
|
@@ -336,7 +355,11 @@ describe("membership rules", () => {
|
|
|
336
355
|
await seedOrg("acme", "auth0|alice");
|
|
337
356
|
const alice = account("auth0|alice", "alice@example.com");
|
|
338
357
|
await rules.onAccountCreated(alice, userCaller(alice.metadata!.id));
|
|
339
|
-
await grantPath.revokeOrgAccess(
|
|
358
|
+
await grantPath.revokeOrgAccess(
|
|
359
|
+
alice.metadata!.id,
|
|
360
|
+
"acme",
|
|
361
|
+
userCaller(alice.metadata!.id),
|
|
362
|
+
);
|
|
340
363
|
expect(policies.rows.size).toBe(0);
|
|
341
364
|
// No blueprint at all: only the organization's own creator stamp stands between mallory and admin.
|
|
342
365
|
const mallory = account("auth0|mallory", "mallory@example.com");
|
|
@@ -646,6 +669,13 @@ describe("membership rules", () => {
|
|
|
646
669
|
IdentityAccountProvisioningMode.platform_client;
|
|
647
670
|
expect(isPersonAccount(endUser)).toBe(false);
|
|
648
671
|
});
|
|
672
|
+
|
|
673
|
+
it("a federated account is not: its subject and its email are the ones its identity provider asserted", () => {
|
|
674
|
+
const federated = account("okta|00u1", OPERATOR_EMAIL);
|
|
675
|
+
federated.spec!.provisioningMode =
|
|
676
|
+
IdentityAccountProvisioningMode.federated;
|
|
677
|
+
expect(isPersonAccount(federated)).toBe(false);
|
|
678
|
+
});
|
|
649
679
|
});
|
|
650
680
|
|
|
651
681
|
describe("ensureRolesForExistingAccounts", () => {
|
|
@@ -671,6 +701,18 @@ describe("membership rules", () => {
|
|
|
671
701
|
);
|
|
672
702
|
});
|
|
673
703
|
|
|
704
|
+
it("a federated account earns no role, though its provider asserted the founder's subject and the operator's email", async () => {
|
|
705
|
+
await seedOrg("acme", "auth0|alice");
|
|
706
|
+
await seedOrg("globex", "auth0|carol");
|
|
707
|
+
const federated = await seedAccount("auth0|alice", OPERATOR_EMAIL, 100, {
|
|
708
|
+
federated: true,
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
await rules.ensureRolesForExistingAccounts();
|
|
712
|
+
|
|
713
|
+
expect(rolesOf(federated.metadata!.id)).toEqual([]);
|
|
714
|
+
});
|
|
715
|
+
|
|
674
716
|
it("a second call is a no-op — the marker short-circuits before any read", async () => {
|
|
675
717
|
await seedOrg("acme", "auth0|alice");
|
|
676
718
|
await seedAccount("auth0|alice", "alice@example.com", 100);
|
|
@@ -52,6 +52,7 @@ const CONTRACT_CASE_NAMES = [
|
|
|
52
52
|
"countDistinctPrincipalsByResource counts (kind, id) pairs, not rows, optionally by principal kind",
|
|
53
53
|
"findScopeTuple skips identity_account and team principals and owner and creator relations",
|
|
54
54
|
"deleteById removes the row; the triple is free to be granted again",
|
|
55
|
+
"a change record changes nothing about the row: save and deleteById behave as without one",
|
|
55
56
|
"deleteById of an unknown id resolves",
|
|
56
57
|
"a disconnected store is an infrastructure fault, never 'not found'",
|
|
57
58
|
"two concurrent saves of one triple end in one row and DuplicatePolicyErrors only",
|
|
@@ -61,7 +61,12 @@ import { policyIdFor } from "../constants.js";
|
|
|
61
61
|
import { newIamPolicyGrantPath } from "../grant-path.js";
|
|
62
62
|
import { newBuiltInRoleLifecycle } from "../role-lifecycle.js";
|
|
63
63
|
import type { IamPolicyStore } from "../store.js";
|
|
64
|
-
import {
|
|
64
|
+
import {
|
|
65
|
+
NO_RECORDED_CREATORS,
|
|
66
|
+
fakeIamPolicyStore,
|
|
67
|
+
orgRole,
|
|
68
|
+
triple,
|
|
69
|
+
} from "./support.js";
|
|
65
70
|
import type { RecordedEvent } from "./support.js";
|
|
66
71
|
|
|
67
72
|
const ALICE_SUBJECT = "auth0|alice";
|
|
@@ -129,6 +134,7 @@ function lifecycleOver(
|
|
|
129
134
|
}),
|
|
130
135
|
);
|
|
131
136
|
const grantPath = newIamPolicyGrantPath({
|
|
137
|
+
creators: NO_RECORDED_CREATORS,
|
|
132
138
|
policies: store,
|
|
133
139
|
lifecycle: undefined,
|
|
134
140
|
logger: silentLogger,
|
|
@@ -230,17 +236,26 @@ describe("onResourceDeleted: the rows die with the resource", () => {
|
|
|
230
236
|
it("an organization's deletion removes every row on it, as resource and as principal", async () => {
|
|
231
237
|
const recorded: RecordedEvent[] = [];
|
|
232
238
|
const { lifecycle, grantPath, store } = lifecycleOver(recorded);
|
|
233
|
-
await grantPath.grant(
|
|
234
|
-
|
|
239
|
+
await grantPath.grant(
|
|
240
|
+
orgRole(ALICE, "owner", "acme"),
|
|
241
|
+
caller(ALICE),
|
|
242
|
+
"grant",
|
|
243
|
+
);
|
|
244
|
+
await grantPath.grant(
|
|
245
|
+
orgRole(ALICE, "member", "acme"),
|
|
246
|
+
caller(ALICE),
|
|
247
|
+
"grant",
|
|
248
|
+
);
|
|
235
249
|
await grantPath.grant(
|
|
236
250
|
triple({ kind: "organization", id: "acme" }, "organization", {
|
|
237
251
|
kind: "agent",
|
|
238
252
|
id: AGENT,
|
|
239
253
|
}),
|
|
240
254
|
caller(ALICE),
|
|
255
|
+
"structural",
|
|
241
256
|
);
|
|
242
257
|
const unrelated = orgRole(ALICE, "member", "globex");
|
|
243
|
-
await grantPath.grant(unrelated, caller(ALICE));
|
|
258
|
+
await grantPath.grant(unrelated, caller(ALICE), "grant");
|
|
244
259
|
recorded.length = 0;
|
|
245
260
|
|
|
246
261
|
await lifecycle.onResourceDeleted(
|
|
@@ -263,10 +278,22 @@ describe("onResourceDeleted: the rows die with the resource", () => {
|
|
|
263
278
|
it("an identity account's deletion removes every row it holds anywhere", async () => {
|
|
264
279
|
const recorded: RecordedEvent[] = [];
|
|
265
280
|
const { lifecycle, grantPath, store } = lifecycleOver(recorded);
|
|
266
|
-
await grantPath.grant(
|
|
267
|
-
|
|
281
|
+
await grantPath.grant(
|
|
282
|
+
orgRole(ALICE, "owner", "acme"),
|
|
283
|
+
caller(ALICE),
|
|
284
|
+
"grant",
|
|
285
|
+
);
|
|
286
|
+
await grantPath.grant(
|
|
287
|
+
orgRole(ALICE, "member", "globex"),
|
|
288
|
+
caller(ALICE),
|
|
289
|
+
"grant",
|
|
290
|
+
);
|
|
268
291
|
const bob = accountIdFor("auth0|bob");
|
|
269
|
-
await grantPath.grant(
|
|
292
|
+
await grantPath.grant(
|
|
293
|
+
orgRole(bob, "member", "acme"),
|
|
294
|
+
caller(ALICE),
|
|
295
|
+
"grant",
|
|
296
|
+
);
|
|
270
297
|
recorded.length = 0;
|
|
271
298
|
|
|
272
299
|
await lifecycle.onResourceDeleted(
|
|
@@ -296,6 +323,7 @@ describe("onResourceDeleted: the rows die with the resource", () => {
|
|
|
296
323
|
id: AGENT,
|
|
297
324
|
}),
|
|
298
325
|
caller(ALICE),
|
|
326
|
+
"grant",
|
|
299
327
|
);
|
|
300
328
|
recorded.length = 0;
|
|
301
329
|
|
|
@@ -315,6 +343,7 @@ describe("the rest of the contract", () => {
|
|
|
315
343
|
kind: ApiResourceKind.agent,
|
|
316
344
|
resourceId: AGENT,
|
|
317
345
|
orgId: "acme",
|
|
346
|
+
caller: caller(ALICE),
|
|
318
347
|
shapesToCreate: ["org-viewer"],
|
|
319
348
|
shapesToDelete: [],
|
|
320
349
|
});
|
|
@@ -349,7 +378,11 @@ describe("the rest of the contract", () => {
|
|
|
349
378
|
deleteById: () => Promise.reject(new Error("disk full")),
|
|
350
379
|
};
|
|
351
380
|
const { lifecycle, grantPath } = lifecycleOver([], faulty);
|
|
352
|
-
await grantPath.grant(
|
|
381
|
+
await grantPath.grant(
|
|
382
|
+
orgRole(ALICE, "owner", "acme"),
|
|
383
|
+
caller(ALICE),
|
|
384
|
+
"grant",
|
|
385
|
+
);
|
|
353
386
|
|
|
354
387
|
await expect(
|
|
355
388
|
lifecycle.onResourceDeleted(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pins roles.ts (20260913.01 slice 5): the
|
|
2
|
+
* Pins roles.ts (20260913.01 slice 5): the six assignable roles' display
|
|
3
3
|
* metadata and the allowlist that keeps structural relations out of every
|
|
4
4
|
* access listing — moved from the cloud's iam/policy/roles.ts (the Java
|
|
5
5
|
* IamRoleMetadata port). The allowlist is proven by construction here:
|
|
@@ -15,13 +15,14 @@ import {
|
|
|
15
15
|
} from "../roles.js";
|
|
16
16
|
|
|
17
17
|
describe("the assignable-role allowlist", () => {
|
|
18
|
-
it("is exactly the
|
|
18
|
+
it("is exactly the six roles a person can hold, in display order", () => {
|
|
19
19
|
expect(assignableRelations()).toEqual([
|
|
20
20
|
"owner",
|
|
21
21
|
"admin",
|
|
22
22
|
"member",
|
|
23
23
|
"viewer",
|
|
24
24
|
"participant",
|
|
25
|
+
"editor",
|
|
25
26
|
]);
|
|
26
27
|
});
|
|
27
28
|
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* names no relation qualifier; a team is granted only its kind's team
|
|
13
13
|
* roles (never ownership, never on a kind that lists none), always as its
|
|
14
14
|
* members, and nothing at all under open source's organization-only scope.
|
|
15
|
+
* The editor role is granted on the three blueprints to a person or a team
|
|
16
|
+
* where the scope passes the proto through, refused on a kind that does not
|
|
17
|
+
* list it, and granted nowhere under open source's scope.
|
|
15
18
|
*
|
|
16
19
|
* Grant and Revoke are proven for the one thing a step adds over the
|
|
17
20
|
* grant path: the result they leave under POLICY_RESULT_KEY (the revoke
|
|
@@ -44,6 +47,7 @@ import type { Authorizer, AuthzCheck } from "../../../extensions/authorizer.js";
|
|
|
44
47
|
import type { CallerIdentity } from "../../../extensions/identity.js";
|
|
45
48
|
import type { PolicyGrantScope } from "../../../extensions/policy-grant-scope.js";
|
|
46
49
|
import { trustedLocalIdentityFor } from "../../../pipeline/interceptors/auth.js";
|
|
50
|
+
import { grantableRolesFor } from "../../../pipeline/apiresource-meta.js";
|
|
47
51
|
import { RequestContext } from "../../../pipeline/request-context.js";
|
|
48
52
|
import {
|
|
49
53
|
LAST_OWNER_MESSAGE,
|
|
@@ -71,7 +75,12 @@ import {
|
|
|
71
75
|
orgAccessOwnerRoleChange,
|
|
72
76
|
specOwnerRoleChange,
|
|
73
77
|
} from "../steps.js";
|
|
74
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
NO_RECORDED_CREATORS,
|
|
80
|
+
fakeIamPolicyStore,
|
|
81
|
+
orgRole,
|
|
82
|
+
triple,
|
|
83
|
+
} from "./support.js";
|
|
75
84
|
|
|
76
85
|
const caller = trustedLocalIdentityFor({
|
|
77
86
|
email: "operator@example.com",
|
|
@@ -333,6 +342,60 @@ describe("ValidateGrantableRole", () => {
|
|
|
333
342
|
});
|
|
334
343
|
});
|
|
335
344
|
|
|
345
|
+
describe("the editor role", () => {
|
|
346
|
+
// The hosted edition's scope narrows nothing: every role the proto lists
|
|
347
|
+
// is grantable (the cloud's policy grant scope).
|
|
348
|
+
const everyProtoRole = newValidateGrantableRoleStep({
|
|
349
|
+
grantableRoles: (kind) => grantableRolesFor(kind),
|
|
350
|
+
});
|
|
351
|
+
const person = { kind: "identity_account", id: "ida_bob" };
|
|
352
|
+
const team = { kind: "team", id: "tm_sre", relation: "member" };
|
|
353
|
+
const blueprints = [
|
|
354
|
+
["agent", "agt_1"],
|
|
355
|
+
["workflow", "wfl_1"],
|
|
356
|
+
["mcp_server", "mcp_1"],
|
|
357
|
+
] as const;
|
|
358
|
+
|
|
359
|
+
it("is granted on an agent, a workflow and an MCP server, to a person and to a team", () => {
|
|
360
|
+
for (const [kind, id] of blueprints) {
|
|
361
|
+
for (const principal of [person, team]) {
|
|
362
|
+
expect(
|
|
363
|
+
everyProtoRole.execute(
|
|
364
|
+
contextOf(triple(principal, "editor", { kind, id })),
|
|
365
|
+
),
|
|
366
|
+
`${principal.kind} on ${kind}`,
|
|
367
|
+
).toBeUndefined();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it("is refused on a kind that does not list it, with the kind's own roles named", async () => {
|
|
373
|
+
const error = await refusal(() =>
|
|
374
|
+
everyProtoRole.execute(
|
|
375
|
+
contextOf(triple(person, "editor", { kind: "skill", id: "skl_1" })),
|
|
376
|
+
),
|
|
377
|
+
);
|
|
378
|
+
expect(error.code).toBe(Code.InvalidArgument);
|
|
379
|
+
expect(error.rawMessage).toBe(
|
|
380
|
+
roleNotGrantableMessage("editor", "skill", ["owner", "viewer"]),
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("is granted nowhere under open source's organization-only scope", async () => {
|
|
385
|
+
for (const [kind, id] of blueprints) {
|
|
386
|
+
const error = await refusal(() =>
|
|
387
|
+
organizationOnly.execute(
|
|
388
|
+
contextOf(triple(person, "editor", { kind, id })),
|
|
389
|
+
),
|
|
390
|
+
);
|
|
391
|
+
expect(error.code, kind).toBe(Code.Unimplemented);
|
|
392
|
+
expect(error.rawMessage, kind).toBe(
|
|
393
|
+
PER_RESOURCE_GRANTS_UNIMPLEMENTED_MESSAGE,
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
336
399
|
it("a scope can only NARROW the proto: a role it adds is clipped from the list", async () => {
|
|
337
400
|
const widening = newValidateGrantableRoleStep(
|
|
338
401
|
scopeOf(
|
|
@@ -382,6 +445,7 @@ describe("ValidateGrantableRole", () => {
|
|
|
382
445
|
describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
|
|
383
446
|
function pathOverFreshStore() {
|
|
384
447
|
return newIamPolicyGrantPath({
|
|
448
|
+
creators: NO_RECORDED_CREATORS,
|
|
385
449
|
policies: fakeIamPolicyStore(),
|
|
386
450
|
lifecycle: undefined,
|
|
387
451
|
logger: silent,
|
|
@@ -392,9 +456,9 @@ describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
|
|
|
392
456
|
const path = pathOverFreshStore();
|
|
393
457
|
const spec = orgRole("ida_bob", "member", "acme");
|
|
394
458
|
const first = contextOf(spec);
|
|
395
|
-
await newGrantStep(path).execute(first);
|
|
459
|
+
await newGrantStep(path, "grant").execute(first);
|
|
396
460
|
const second = contextOf(spec);
|
|
397
|
-
await newGrantStep(path).execute(second);
|
|
461
|
+
await newGrantStep(path, "grant").execute(second);
|
|
398
462
|
expect((first.get(POLICY_RESULT_KEY) as IamPolicy).metadata?.id).toBe(
|
|
399
463
|
policyIdFor(spec),
|
|
400
464
|
);
|
|
@@ -406,7 +470,7 @@ describe("Grant and Revoke leave their result under POLICY_RESULT_KEY", () => {
|
|
|
406
470
|
it("Revoke leaves the revoked row, or the default instance when there was none (Java's idempotent delete)", async () => {
|
|
407
471
|
const path = pathOverFreshStore();
|
|
408
472
|
const spec = orgRole("ida_bob", "member", "acme");
|
|
409
|
-
await path.grant(spec, caller);
|
|
473
|
+
await path.grant(spec, caller, "grant");
|
|
410
474
|
const revoked = contextOf(spec);
|
|
411
475
|
await newRevokeStep(path).execute(revoked);
|
|
412
476
|
expect((revoked.get(POLICY_RESULT_KEY) as IamPolicy).metadata?.id).toBe(
|
|
@@ -468,9 +532,14 @@ describe("owner is assigned by owners", () => {
|
|
|
468
532
|
roles: ReadonlyArray<readonly [string, string]>,
|
|
469
533
|
): Promise<ReturnType<typeof fakeIamPolicyStore> & { readonly ownerReads: () => number }> {
|
|
470
534
|
const store = fakeIamPolicyStore();
|
|
471
|
-
const path = newIamPolicyGrantPath({
|
|
535
|
+
const path = newIamPolicyGrantPath({
|
|
536
|
+
creators: NO_RECORDED_CREATORS,
|
|
537
|
+
policies: store,
|
|
538
|
+
lifecycle: undefined,
|
|
539
|
+
logger: silent,
|
|
540
|
+
});
|
|
472
541
|
for (const [account, role] of roles) {
|
|
473
|
-
await path.grant(orgRole(account, role, "acme"), caller);
|
|
542
|
+
await path.grant(orgRole(account, role, "acme"), caller, "grant");
|
|
474
543
|
}
|
|
475
544
|
let reads = 0;
|
|
476
545
|
const read = store.findByResourceWithRelations.bind(store);
|
|
@@ -16,9 +16,12 @@ import { IamPolicySpecSchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1
|
|
|
16
16
|
|
|
17
17
|
import type {
|
|
18
18
|
PolicyGrantedEvent,
|
|
19
|
+
OrganizationAffiliationEvent,
|
|
19
20
|
PolicyRevokedEvent,
|
|
20
21
|
ResourceAuthorizationLifecycle,
|
|
21
22
|
} from "../../../extensions/resource-authorization.js";
|
|
23
|
+
import type { PolicyChangeRecord } from "../change.js";
|
|
24
|
+
import type { ResourceCreators } from "../grant-path.js";
|
|
22
25
|
import { DuplicatePolicyError } from "../store.js";
|
|
23
26
|
import type { IamPolicyStore } from "../store.js";
|
|
24
27
|
|
|
@@ -52,6 +55,24 @@ export function triple(
|
|
|
52
55
|
});
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
/** A server that stores no resource rows: nothing the sweep meets is anyone's authorship. */
|
|
59
|
+
export const NO_RECORDED_CREATORS: ResourceCreators = {
|
|
60
|
+
async creatorOf() {
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/** Recorded creators by `kind:id`, the removal sweep's authorship read. */
|
|
66
|
+
export function recordedCreators(
|
|
67
|
+
creators: Readonly<Record<string, string>>,
|
|
68
|
+
): ResourceCreators {
|
|
69
|
+
return {
|
|
70
|
+
async creatorOf(kind, id) {
|
|
71
|
+
return creators[`${kind}:${id}`];
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
55
76
|
/** What a recording fixture saw, in order. */
|
|
56
77
|
export type RecordedEvent =
|
|
57
78
|
| { readonly kind: "row-save"; readonly id: string }
|
|
@@ -65,10 +86,23 @@ export type RecordedEvent =
|
|
|
65
86
|
readonly kind: "revoked";
|
|
66
87
|
readonly id: string | undefined;
|
|
67
88
|
readonly relation: string;
|
|
89
|
+
}
|
|
90
|
+
| {
|
|
91
|
+
readonly kind: "affiliation-changing" | "affiliation-changed";
|
|
92
|
+
readonly pair: string;
|
|
68
93
|
};
|
|
69
94
|
|
|
95
|
+
/** A change record the fake store was handed, beside the write it came with. */
|
|
96
|
+
export interface RecordedChange {
|
|
97
|
+
readonly op: "save" | "delete";
|
|
98
|
+
readonly id: string;
|
|
99
|
+
readonly record: PolicyChangeRecord | undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
70
102
|
export interface FakeIamPolicyStore extends IamPolicyStore {
|
|
71
103
|
readonly rows: Map<string, IamPolicy>;
|
|
104
|
+
/** Every save and delete that changed a row, with the record it carried. */
|
|
105
|
+
readonly changes: RecordedChange[];
|
|
72
106
|
}
|
|
73
107
|
|
|
74
108
|
/** An in-memory store with the adapter's primary-key semantics; writes are recorded when a log is given. */
|
|
@@ -76,6 +110,7 @@ export function fakeIamPolicyStore(
|
|
|
76
110
|
recorded?: RecordedEvent[],
|
|
77
111
|
): FakeIamPolicyStore {
|
|
78
112
|
const rows = new Map<string, IamPolicy>();
|
|
113
|
+
const changes: RecordedChange[] = [];
|
|
79
114
|
const all = (): IamPolicy[] => [...rows.values()];
|
|
80
115
|
const matches = (
|
|
81
116
|
policy: IamPolicy,
|
|
@@ -92,16 +127,20 @@ export function fakeIamPolicyStore(
|
|
|
92
127
|
(resourceId === undefined || policy.spec?.resource?.id === resourceId);
|
|
93
128
|
return {
|
|
94
129
|
rows,
|
|
95
|
-
|
|
130
|
+
changes,
|
|
131
|
+
async save(policy, record) {
|
|
96
132
|
const id = policy.metadata?.id ?? "";
|
|
97
133
|
if (rows.has(id)) {
|
|
98
134
|
throw new DuplicatePolicyError(`IAM policy '${id}' already exists`);
|
|
99
135
|
}
|
|
100
136
|
rows.set(id, policy);
|
|
137
|
+
changes.push({ op: "save", id, record });
|
|
101
138
|
recorded?.push({ kind: "row-save", id });
|
|
102
139
|
},
|
|
103
|
-
async deleteById(id) {
|
|
104
|
-
rows.delete(id)
|
|
140
|
+
async deleteById(id, record) {
|
|
141
|
+
if (rows.delete(id)) {
|
|
142
|
+
changes.push({ op: "delete", id, record });
|
|
143
|
+
}
|
|
105
144
|
recorded?.push({ kind: "row-delete", id });
|
|
106
145
|
},
|
|
107
146
|
async findById(id) {
|
|
@@ -165,9 +204,34 @@ export function fakeIamPolicyStore(
|
|
|
165
204
|
/** A lifecycle that records the two policy hooks and can be told to fail either. */
|
|
166
205
|
export function recordingLifecycle(
|
|
167
206
|
recorded: RecordedEvent[],
|
|
168
|
-
faults: {
|
|
207
|
+
faults: {
|
|
208
|
+
readonly granted?: Error;
|
|
209
|
+
readonly revoked?: Error;
|
|
210
|
+
readonly changing?: Error;
|
|
211
|
+
} = {},
|
|
212
|
+
options: { readonly affiliation?: boolean } = {},
|
|
169
213
|
): ResourceAuthorizationLifecycle {
|
|
214
|
+
const pair = (event: OrganizationAffiliationEvent): string =>
|
|
215
|
+
`${event.identityAccountId}@${event.organizationId}`;
|
|
216
|
+
const affiliation: Pick<
|
|
217
|
+
ResourceAuthorizationLifecycle,
|
|
218
|
+
"onOrganizationAffiliationChanging" | "onOrganizationAffiliationChanged"
|
|
219
|
+
> =
|
|
220
|
+
options.affiliation === true
|
|
221
|
+
? {
|
|
222
|
+
async onOrganizationAffiliationChanging(event) {
|
|
223
|
+
if (faults.changing !== undefined) {
|
|
224
|
+
throw faults.changing;
|
|
225
|
+
}
|
|
226
|
+
recorded.push({ kind: "affiliation-changing", pair: pair(event) });
|
|
227
|
+
},
|
|
228
|
+
async onOrganizationAffiliationChanged(event) {
|
|
229
|
+
recorded.push({ kind: "affiliation-changed", pair: pair(event) });
|
|
230
|
+
},
|
|
231
|
+
}
|
|
232
|
+
: {};
|
|
170
233
|
return {
|
|
234
|
+
...affiliation,
|
|
171
235
|
async onResourceCreated() {},
|
|
172
236
|
async onResourceDeleted() {},
|
|
173
237
|
async onVisibilityChanged() {},
|