@stigmer/server 3.21.0 → 3.22.1-dev.20260922095755
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 +4 -8
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +5 -9
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/derived-tuples.d.ts.map +1 -1
- package/dist/authorization/derived-tuples.js +10 -25
- package/dist/authorization/derived-tuples.js.map +1 -1
- package/dist/authorization/evaluator.d.ts +13 -8
- package/dist/authorization/evaluator.d.ts.map +1 -1
- package/dist/authorization/evaluator.js +4 -20
- package/dist/authorization/evaluator.js.map +1 -1
- package/dist/authorization/list-read-scope.d.ts.map +1 -1
- package/dist/authorization/list-read-scope.js +24 -20
- package/dist/authorization/list-read-scope.js.map +1 -1
- package/dist/authorization/model/agent.d.ts.map +1 -1
- package/dist/authorization/model/agent.js +4 -5
- package/dist/authorization/model/agent.js.map +1 -1
- package/dist/authorization/model/agent_instance.d.ts.map +1 -1
- package/dist/authorization/model/agent_instance.js +2 -2
- package/dist/authorization/model/agent_instance.js.map +1 -1
- package/dist/authorization/model/mcp_server.d.ts.map +1 -1
- package/dist/authorization/model/mcp_server.js +2 -2
- package/dist/authorization/model/mcp_server.js.map +1 -1
- package/dist/authorization/model/organization.d.ts.map +1 -1
- package/dist/authorization/model/organization.js +2 -0
- package/dist/authorization/model/organization.js.map +1 -1
- package/dist/authorization/model/plugin.d.ts.map +1 -1
- package/dist/authorization/model/plugin.js +3 -4
- package/dist/authorization/model/plugin.js.map +1 -1
- package/dist/authorization/model/rewrite.d.ts +8 -10
- package/dist/authorization/model/rewrite.d.ts.map +1 -1
- package/dist/authorization/model/rewrite.js +0 -3
- package/dist/authorization/model/rewrite.js.map +1 -1
- package/dist/authorization/model/skill.d.ts.map +1 -1
- package/dist/authorization/model/skill.js +2 -2
- package/dist/authorization/model/skill.js.map +1 -1
- package/dist/authorization/model/workflow.d.ts.map +1 -1
- package/dist/authorization/model/workflow.js +2 -2
- package/dist/authorization/model/workflow.js.map +1 -1
- package/dist/authorization/model/workflow_instance.d.ts.map +1 -1
- package/dist/authorization/model/workflow_instance.js +2 -2
- package/dist/authorization/model/workflow_instance.js.map +1 -1
- package/dist/authorization/organization-directory.d.ts.map +1 -1
- package/dist/authorization/organization-directory.js +2 -3
- package/dist/authorization/organization-directory.js.map +1 -1
- package/dist/authorization/store-test-kit.d.ts +0 -6
- package/dist/authorization/store-test-kit.d.ts.map +1 -1
- package/dist/authorization/store-test-kit.js +16 -62
- package/dist/authorization/store-test-kit.js.map +1 -1
- package/dist/authorization/tuples.d.ts +13 -32
- package/dist/authorization/tuples.d.ts.map +1 -1
- package/dist/authorization/tuples.js +3 -11
- package/dist/authorization/tuples.js.map +1 -1
- package/dist/domain/agent/controller.d.ts.map +1 -1
- package/dist/domain/agent/controller.js +6 -4
- package/dist/domain/agent/controller.js.map +1 -1
- package/dist/domain/agentchannel/controller.d.ts.map +1 -1
- package/dist/domain/agentchannel/controller.js +9 -2
- package/dist/domain/agentchannel/controller.js.map +1 -1
- package/dist/domain/agentchannel/steps.d.ts +19 -0
- package/dist/domain/agentchannel/steps.d.ts.map +1 -1
- package/dist/domain/agentchannel/steps.js +32 -0
- package/dist/domain/agentchannel/steps.js.map +1 -1
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +3 -1
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentinstance/controller.d.ts +5 -5
- package/dist/domain/agentinstance/controller.d.ts.map +1 -1
- package/dist/domain/agentinstance/controller.js +9 -5
- package/dist/domain/agentinstance/controller.js.map +1 -1
- package/dist/domain/agentinstance/steps.d.ts +43 -8
- package/dist/domain/agentinstance/steps.d.ts.map +1 -1
- package/dist/domain/agentinstance/steps.js +71 -8
- package/dist/domain/agentinstance/steps.js.map +1 -1
- package/dist/domain/agentshare/constants.d.ts +6 -11
- package/dist/domain/agentshare/constants.d.ts.map +1 -1
- package/dist/domain/agentshare/constants.js +8 -16
- package/dist/domain/agentshare/constants.js.map +1 -1
- package/dist/domain/agentshare/controller.d.ts.map +1 -1
- package/dist/domain/agentshare/controller.js +10 -2
- package/dist/domain/agentshare/controller.js.map +1 -1
- package/dist/domain/agentshare/steps.d.ts +61 -10
- package/dist/domain/agentshare/steps.d.ts.map +1 -1
- package/dist/domain/agentshare/steps.js +121 -117
- package/dist/domain/agentshare/steps.js.map +1 -1
- package/dist/domain/artifact/controller.js +21 -25
- package/dist/domain/artifact/controller.js.map +1 -1
- package/dist/domain/channelapp/controller.d.ts.map +1 -1
- package/dist/domain/channelapp/controller.js +2 -0
- package/dist/domain/channelapp/controller.js.map +1 -1
- package/dist/domain/environment/controller.d.ts.map +1 -1
- package/dist/domain/environment/controller.js +4 -3
- package/dist/domain/environment/controller.js.map +1 -1
- package/dist/domain/executioncontext/controller.d.ts.map +1 -1
- package/dist/domain/executioncontext/controller.js +4 -1
- package/dist/domain/executioncontext/controller.js.map +1 -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/mcpserver/connect.d.ts.map +1 -1
- package/dist/domain/mcpserver/connect.js +8 -7
- package/dist/domain/mcpserver/connect.js.map +1 -1
- package/dist/domain/mcpserver/controller.d.ts.map +1 -1
- package/dist/domain/mcpserver/controller.js +5 -4
- package/dist/domain/mcpserver/controller.js.map +1 -1
- package/dist/domain/mcpserver/start-connect.d.ts.map +1 -1
- package/dist/domain/mcpserver/start-connect.js +8 -7
- package/dist/domain/mcpserver/start-connect.js.map +1 -1
- package/dist/domain/memory/controller.d.ts.map +1 -1
- package/dist/domain/memory/controller.js +6 -1
- package/dist/domain/memory/controller.js.map +1 -1
- package/dist/domain/memory/steps.d.ts +23 -0
- package/dist/domain/memory/steps.d.ts.map +1 -1
- package/dist/domain/memory/steps.js +35 -0
- package/dist/domain/memory/steps.js.map +1 -1
- package/dist/domain/oauthapp/controller.d.ts.map +1 -1
- package/dist/domain/oauthapp/controller.js +2 -0
- package/dist/domain/oauthapp/controller.js.map +1 -1
- package/dist/domain/plugin/controller.d.ts.map +1 -1
- package/dist/domain/plugin/controller.js +6 -27
- package/dist/domain/plugin/controller.js.map +1 -1
- package/dist/domain/plugin/push.d.ts +7 -5
- package/dist/domain/plugin/push.d.ts.map +1 -1
- package/dist/domain/plugin/push.js +8 -14
- package/dist/domain/plugin/push.js.map +1 -1
- package/dist/domain/schedule/controller.d.ts.map +1 -1
- package/dist/domain/schedule/controller.js +10 -2
- package/dist/domain/schedule/controller.js.map +1 -1
- package/dist/domain/schedule/steps.d.ts +19 -0
- package/dist/domain/schedule/steps.d.ts.map +1 -1
- package/dist/domain/schedule/steps.js +32 -0
- package/dist/domain/schedule/steps.js.map +1 -1
- package/dist/domain/session/controller.d.ts.map +1 -1
- package/dist/domain/session/controller.js +3 -2
- package/dist/domain/session/controller.js.map +1 -1
- package/dist/domain/session/steps.d.ts +8 -9
- package/dist/domain/session/steps.d.ts.map +1 -1
- package/dist/domain/session/steps.js +17 -21
- package/dist/domain/session/steps.js.map +1 -1
- package/dist/domain/skill/controller.d.ts.map +1 -1
- package/dist/domain/skill/controller.js +8 -19
- package/dist/domain/skill/controller.js.map +1 -1
- package/dist/domain/workflow/agent-call-references.d.ts +54 -0
- package/dist/domain/workflow/agent-call-references.d.ts.map +1 -0
- package/dist/domain/workflow/agent-call-references.js +97 -0
- package/dist/domain/workflow/agent-call-references.js.map +1 -0
- package/dist/domain/workflow/controller.d.ts.map +1 -1
- package/dist/domain/workflow/controller.js +44 -113
- package/dist/domain/workflow/controller.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.d.ts +10 -1
- package/dist/domain/workflow/validation/task-config-constraints.d.ts.map +1 -1
- package/dist/domain/workflow/validation/task-config-constraints.js +3 -2
- package/dist/domain/workflow/validation/task-config-constraints.js.map +1 -1
- package/dist/domain/workflow/version-resolution.d.ts +5 -0
- package/dist/domain/workflow/version-resolution.d.ts.map +1 -0
- package/dist/domain/workflow/version-resolution.js +113 -0
- package/dist/domain/workflow/version-resolution.js.map +1 -0
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +4 -2
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowinstance/controller.d.ts.map +1 -1
- package/dist/domain/workflowinstance/controller.js +9 -5
- package/dist/domain/workflowinstance/controller.js.map +1 -1
- package/dist/domain/workflowinstance/steps.d.ts +20 -0
- package/dist/domain/workflowinstance/steps.d.ts.map +1 -1
- package/dist/domain/workflowinstance/steps.js +39 -0
- package/dist/domain/workflowinstance/steps.js.map +1 -1
- package/dist/extensions/authorization-queries.d.ts +6 -5
- package/dist/extensions/authorization-queries.d.ts.map +1 -1
- package/dist/extensions/identity.d.ts +19 -0
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js +22 -3
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +42 -8
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js +13 -2
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/extensions/resource-authorization.d.ts +3 -2
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +12 -3
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +21 -10
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +9 -3
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +9 -11
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/dist/pipeline/steps/authorize-resolved-target.d.ts +88 -0
- package/dist/pipeline/steps/authorize-resolved-target.d.ts.map +1 -0
- package/dist/pipeline/steps/authorize-resolved-target.js +36 -0
- package/dist/pipeline/steps/authorize-resolved-target.js.map +1 -0
- package/dist/pipeline/steps/authorize.d.ts +27 -0
- package/dist/pipeline/steps/authorize.d.ts.map +1 -1
- package/dist/pipeline/steps/authorize.js +49 -10
- package/dist/pipeline/steps/authorize.js.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.js +2 -1
- package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
- package/dist/pipeline/steps/guard-reserved-labels.d.ts.map +1 -1
- package/dist/pipeline/steps/guard-reserved-labels.js +6 -7
- package/dist/pipeline/steps/guard-reserved-labels.js.map +1 -1
- package/dist/pipeline/steps/helpers.d.ts +9 -5
- package/dist/pipeline/steps/helpers.d.ts.map +1 -1
- package/dist/pipeline/steps/helpers.js +11 -15
- package/dist/pipeline/steps/helpers.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +178 -20
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +344 -43
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/pipeline/steps/version-history.d.ts +11 -0
- package/dist/pipeline/steps/version-history.d.ts.map +1 -1
- package/dist/pipeline/steps/version-history.js +26 -0
- package/dist/pipeline/steps/version-history.js.map +1 -1
- package/dist/query/search/controller.js +0 -1
- package/dist/query/search/controller.js.map +1 -1
- package/dist/query/search/criteria.d.ts +1 -5
- package/dist/query/search/criteria.d.ts.map +1 -1
- package/dist/query/search/criteria.js +3 -13
- package/dist/query/search/criteria.js.map +1 -1
- package/dist/query/search/handler.d.ts +5 -4
- package/dist/query/search/handler.d.ts.map +1 -1
- package/dist/query/search/handler.js +7 -6
- package/dist/query/search/handler.js.map +1 -1
- package/dist/query/search/query-store.d.ts.map +1 -1
- package/dist/query/search/query-store.js +0 -2
- package/dist/query/search/query-store.js.map +1 -1
- package/dist/store/interface.d.ts +3 -6
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +3 -1
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +35 -1
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +4 -9
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/public-visibility-retired.d.ts +67 -0
- package/dist/store/public-visibility-retired.d.ts.map +1 -0
- package/dist/store/public-visibility-retired.js +55 -0
- package/dist/store/public-visibility-retired.js.map +1 -0
- package/dist/store/sqlite/migrations.d.ts +3 -1
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +36 -1
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +4 -8
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/README.md +24 -26
- package/src/authorization/__tests__/authorizer.test.ts +10 -9
- package/src/authorization/__tests__/derived-tuples.test.ts +4 -11
- package/src/authorization/__tests__/evaluator.test.ts +14 -73
- package/src/authorization/__tests__/facts.test.ts +2 -2
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +6 -98
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +4 -61
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +1 -21
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +1 -25
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +1 -3
- package/src/authorization/__tests__/list-read-scope.test.ts +41 -29
- package/src/authorization/__tests__/skip-lane-inventory.test.ts +160 -0
- package/src/authorization/__tests__/store-tests.test.ts +1 -6
- package/src/authorization/__tests__/tuples.test.ts +12 -11
- package/src/authorization/__tests__/wire-permissions.test.ts +5 -5
- package/src/authorization/authorizer.ts +4 -9
- package/src/authorization/derived-tuples.ts +14 -31
- package/src/authorization/evaluator.ts +15 -44
- package/src/authorization/list-read-scope.ts +27 -22
- package/src/authorization/model/__tests__/registry.test.ts +2 -0
- package/src/authorization/model/agent.ts +2 -5
- package/src/authorization/model/agent_instance.ts +0 -2
- package/src/authorization/model/mcp_server.ts +0 -2
- package/src/authorization/model/organization.ts +2 -0
- package/src/authorization/model/plugin.ts +1 -4
- package/src/authorization/model/rewrite.ts +8 -13
- package/src/authorization/model/skill.ts +0 -2
- package/src/authorization/model/workflow.ts +0 -2
- package/src/authorization/model/workflow_instance.ts +0 -2
- package/src/authorization/organization-directory.ts +1 -3
- package/src/authorization/store-test-kit.ts +16 -75
- package/src/authorization/tuples.ts +16 -39
- package/src/domain/agent/__tests__/agent.test.ts +11 -4
- package/src/domain/agent/controller.ts +17 -7
- package/src/domain/agentchannel/__tests__/agentchannel.test.ts +223 -48
- package/src/domain/agentchannel/__tests__/create-authorization.test.ts +58 -0
- package/src/domain/agentchannel/controller.ts +25 -1
- package/src/domain/agentchannel/steps.ts +40 -0
- package/src/domain/agentexecution/controller.ts +6 -1
- package/src/domain/agentinstance/__tests__/create-authorization.composed.test.ts +243 -0
- package/src/domain/agentinstance/__tests__/create-authorization.test.ts +144 -0
- package/src/domain/agentinstance/controller.ts +30 -17
- package/src/domain/agentinstance/steps.ts +82 -8
- package/src/domain/agentshare/__tests__/agentshare.test.ts +196 -172
- package/src/domain/agentshare/__tests__/create-authorization.test.ts +71 -0
- package/src/domain/agentshare/__tests__/member-audience.test.ts +113 -0
- package/src/domain/agentshare/constants.ts +14 -26
- package/src/domain/agentshare/controller.ts +27 -1
- package/src/domain/agentshare/steps.ts +168 -155
- package/src/domain/artifact/controller.ts +18 -22
- package/src/domain/channelapp/controller.ts +10 -0
- package/src/domain/environment/controller.ts +15 -8
- package/src/domain/executioncontext/__tests__/executioncontext.test.ts +1 -0
- package/src/domain/executioncontext/controller.ts +15 -1
- package/src/domain/executioncontext/steps.ts +2 -1
- package/src/domain/mcpserver/__tests__/mcpserver.test.ts +115 -28
- package/src/domain/mcpserver/__tests__/oauth-handshake.test.ts +53 -18
- package/src/domain/mcpserver/connect.ts +11 -10
- package/src/domain/mcpserver/controller.ts +19 -13
- package/src/domain/mcpserver/start-connect.ts +17 -11
- package/src/domain/memory/__tests__/create-authorization.test.ts +59 -0
- package/src/domain/memory/controller.ts +11 -0
- package/src/domain/memory/steps.ts +41 -0
- package/src/domain/oauthapp/controller.ts +10 -0
- package/src/domain/plugin/controller.ts +23 -44
- package/src/domain/plugin/push.ts +8 -16
- package/src/domain/schedule/__tests__/create-authorization.test.ts +58 -0
- package/src/domain/schedule/controller.ts +26 -1
- package/src/domain/schedule/steps.ts +45 -2
- package/src/domain/session/controller.ts +12 -4
- package/src/domain/session/steps.ts +24 -32
- package/src/domain/skill/controller.ts +24 -30
- package/src/domain/workflow/__tests__/agent-call-references.test.ts +222 -0
- package/src/domain/workflow/agent-call-references.ts +157 -0
- package/src/domain/workflow/controller.ts +86 -155
- package/src/domain/workflow/registry/data/task-kind-registry.json +1 -1
- package/src/domain/workflow/validation/task-config-constraints.ts +7 -3
- package/src/domain/workflow/version-resolution.ts +166 -0
- package/src/domain/workflowexecution/controller.ts +7 -2
- package/src/domain/workflowinstance/__tests__/create-authorization.test.ts +109 -0
- package/src/domain/workflowinstance/controller.ts +25 -12
- package/src/domain/workflowinstance/steps.ts +49 -1
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +32 -19
- package/src/extensions/__tests__/composed-support.ts +38 -4
- package/src/extensions/__tests__/extension-composition.test.ts +4 -4
- package/src/extensions/__tests__/identity.test.ts +44 -1
- package/src/extensions/__tests__/list-read-scope-composed.test.ts +96 -7
- package/src/extensions/__tests__/list-read-scope.test.ts +63 -0
- package/src/extensions/authorization-queries.ts +6 -5
- package/src/extensions/identity.ts +23 -5
- package/src/extensions/list-read-scope.ts +48 -8
- package/src/extensions/resource-authorization.ts +3 -5
- package/src/index.ts +0 -1
- package/src/pipeline/__tests__/supports-visibility.test.ts +112 -0
- package/src/pipeline/apiresource-meta.ts +21 -10
- package/src/pipeline/steps/__tests__/authorization-tuples.test.ts +18 -31
- package/src/pipeline/steps/__tests__/authorize-resolved-target.test.ts +285 -0
- package/src/pipeline/steps/__tests__/references.test.ts +703 -0
- package/src/pipeline/steps/authorization-tuples.ts +9 -11
- package/src/pipeline/steps/authorize-resolved-target.ts +129 -0
- package/src/pipeline/steps/authorize.ts +70 -13
- package/src/pipeline/steps/guard-memory-capture.ts +2 -1
- package/src/pipeline/steps/guard-reserved-labels.ts +6 -9
- package/src/pipeline/steps/helpers.ts +11 -15
- package/src/pipeline/steps/references.ts +578 -70
- package/src/pipeline/steps/version-history.ts +34 -0
- package/src/query/search/__tests__/criteria.test.ts +0 -4
- package/src/query/search/__tests__/query-store.test.ts +11 -40
- package/src/query/search/controller.ts +0 -1
- package/src/query/search/criteria.ts +0 -14
- package/src/query/search/handler.ts +6 -7
- package/src/query/search/query-store.ts +0 -2
- package/src/store/__tests__/public-visibility-retired.test.ts +127 -0
- package/src/store/__tests__/store-contract.ts +6 -51
- package/src/store/interface.ts +3 -6
- package/src/store/postgres/__tests__/migrations.test.ts +187 -6
- package/src/store/postgres/__tests__/store-contract.test.ts +0 -2
- package/src/store/postgres/migrations.ts +48 -1
- package/src/store/postgres/store.ts +4 -11
- package/src/store/public-visibility-retired.ts +119 -0
- package/src/store/sqlite/__tests__/migrations.test.ts +191 -5
- package/src/store/sqlite/migrations.ts +45 -1
- package/src/store/sqlite/store.ts +4 -10
- package/dist/pipeline/steps/visibility-gates.d.ts +0 -27
- package/dist/pipeline/steps/visibility-gates.d.ts.map +0 -1
- package/dist/pipeline/steps/visibility-gates.js +0 -139
- package/dist/pipeline/steps/visibility-gates.js.map +0 -1
- package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +0 -98
- package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +0 -52
- package/src/pipeline/steps/__tests__/visibility-gates.test.ts +0 -187
- package/src/pipeline/steps/visibility-gates.ts +0 -174
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AgentShare domain steps — ports pkg/domain/agentshare/controller/steps.go
|
|
3
|
-
* and the get_shared_profile.go helpers: share defaults
|
|
4
|
-
*
|
|
3
|
+
* and the get_shared_profile.go helpers: share defaults and the
|
|
4
|
+
* same-organization invariant on agent_ref, the agent-id rebind pin, the
|
|
5
5
|
* update immutability rules, the uniform-NotFound profile resolution
|
|
6
6
|
* helpers, and the constant-time link-token predicate.
|
|
7
7
|
*
|
|
8
|
+
* A share's agent lives in the share's own organization. The
|
|
9
|
+
* cross-organization arm this domain once carried (a share of another
|
|
10
|
+
* organization's public agent, gated on a public audience and a sweep of
|
|
11
|
+
* the agent's dependencies for public visibility) left with the public
|
|
12
|
+
* level; sharing another organization's agent is done by installing the
|
|
13
|
+
* plugin that carries it and sharing the installed copy. A stored share
|
|
14
|
+
* whose agent is in another organization — a row from before — fails
|
|
15
|
+
* closed at the profile like a dangling reference.
|
|
16
|
+
*
|
|
8
17
|
* OD-1 (deliberate exclusion): Go's boot migration
|
|
9
18
|
* (pkg/domain/agentshare/migration/bootstrap_shares.go — protowire
|
|
10
19
|
* decoding of the REMOVED Agent.spec.sharing fields into AgentShare rows)
|
|
@@ -29,12 +38,8 @@ import type { AgentShare } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v
|
|
|
29
38
|
import { AgentShareStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/status_pb";
|
|
30
39
|
import { SharedAgentProfileSchema } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/io_pb";
|
|
31
40
|
import type { SharedAgentProfile } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/io_pb";
|
|
32
|
-
import { AgentShareAudience } from "@stigmer/protos/ai/stigmer/agentic/agentshare/v1/spec_pb";
|
|
33
|
-
import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
34
|
-
import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
35
|
-
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
36
|
-
import type { ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
37
41
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
42
|
+
import { IamPermission } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
38
43
|
|
|
39
44
|
import {
|
|
40
45
|
failedPreconditionError,
|
|
@@ -44,7 +49,13 @@ import {
|
|
|
44
49
|
} from "../../pipeline/errors.js";
|
|
45
50
|
import type { PipelineStep } from "../../pipeline/pipeline.js";
|
|
46
51
|
import type { RequestContext } from "../../pipeline/request-context.js";
|
|
47
|
-
import {
|
|
52
|
+
import type { Authorizer } from "../../extensions/authorizer.js";
|
|
53
|
+
import {
|
|
54
|
+
AUTHORIZATION_UNAVAILABLE_MESSAGE,
|
|
55
|
+
evaluateAuthorizer,
|
|
56
|
+
} from "../../pipeline/steps/authorize.js";
|
|
57
|
+
import type { AuthorizationTarget } from "../../pipeline/steps/authorize.js";
|
|
58
|
+
import type { GetByReferenceDesc } from "../../pipeline/steps/authorize-resolved-target.js";
|
|
48
59
|
import { EXISTING_RESOURCE_KEY } from "../../pipeline/steps/load-existing.js";
|
|
49
60
|
import type { Store } from "../../store/interface.js";
|
|
50
61
|
import {
|
|
@@ -52,8 +63,7 @@ import {
|
|
|
52
63
|
ORG_REQUIRED_MESSAGE,
|
|
53
64
|
SHARE_LINK_TOKEN_BYTES,
|
|
54
65
|
agentRefImmutableMessage,
|
|
55
|
-
|
|
56
|
-
crossOrgBlockersMessage,
|
|
66
|
+
sameOrgInvariantMessage,
|
|
57
67
|
} from "./constants.js";
|
|
58
68
|
|
|
59
69
|
type AgentShareDesc = typeof AgentShareSchema;
|
|
@@ -61,10 +71,52 @@ type AgentShareDesc = typeof AgentShareSchema;
|
|
|
61
71
|
/**
|
|
62
72
|
* Context key for the agent resolved from spec.agent_ref during
|
|
63
73
|
* create/apply, so later steps never re-load it — Go referencedAgentKey.
|
|
64
|
-
*
|
|
65
|
-
*
|
|
74
|
+
* ResolveShareDefaults writes it; the create lane's authorization step and
|
|
75
|
+
* StampAgentPin read it.
|
|
66
76
|
*/
|
|
67
|
-
const REFERENCED_AGENT_KEY = "agentShareReferencedAgent";
|
|
77
|
+
export const REFERENCED_AGENT_KEY = "agentShareReferencedAgent";
|
|
78
|
+
|
|
79
|
+
/** The deny copy of the agent's bar, the Java AgentShareCreateHandler's. */
|
|
80
|
+
export const SHARE_AGENT_DENIED_MESSAGE =
|
|
81
|
+
"You don't have permission to share this agent";
|
|
82
|
+
|
|
83
|
+
/** The deny copy of the sharing organization's bar, the Java handler's. */
|
|
84
|
+
export const SHARE_ORGANIZATION_DENIED_MESSAGE =
|
|
85
|
+
"You don't have permission to create agent shares in this organization";
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The create lane's authorization questions, for AuthorizeResolvedTarget
|
|
89
|
+
* after ResolveShareDefaults, agent first: can_edit on the agent (sharing
|
|
90
|
+
* puts it in front of a wider audience, an editor's act) and then
|
|
91
|
+
* can_create_agent_share on the organization (a share spends the
|
|
92
|
+
* organization's credits on the open internet, an admin-level act). The
|
|
93
|
+
* RPC is is_skip_authorization because the target is the referenced agent,
|
|
94
|
+
* resolved from a slug, not a request field. The resolve step has already
|
|
95
|
+
* made the reference absolute and refused an agent outside the share's
|
|
96
|
+
* organization, so the two bars are always the same organization's.
|
|
97
|
+
*/
|
|
98
|
+
export function resolveShareCreateTargets(
|
|
99
|
+
ctx: RequestContext<AgentShareDesc>,
|
|
100
|
+
): ReadonlyArray<AuthorizationTarget> {
|
|
101
|
+
const agent = ctx.get(REFERENCED_AGENT_KEY) as Agent | undefined;
|
|
102
|
+
if (agent === undefined) {
|
|
103
|
+
throw new Error("referenced agent not found in context");
|
|
104
|
+
}
|
|
105
|
+
return [
|
|
106
|
+
{
|
|
107
|
+
permission: IamPermission.can_edit,
|
|
108
|
+
resourceKind: ApiResourceKind.agent,
|
|
109
|
+
resourceId: agent.metadata?.id ?? "",
|
|
110
|
+
deniedMessage: SHARE_AGENT_DENIED_MESSAGE,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
permission: IamPermission.can_create_agent_share,
|
|
114
|
+
resourceKind: ApiResourceKind.organization,
|
|
115
|
+
resourceId: ctx.newState.metadata?.org ?? "",
|
|
116
|
+
deniedMessage: SHARE_ORGANIZATION_DENIED_MESSAGE,
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
}
|
|
68
120
|
|
|
69
121
|
/**
|
|
70
122
|
* The single refusal for every anonymous/member resolution miss: share
|
|
@@ -78,6 +130,71 @@ export function sharedNotFound(slug: string): ConnectError {
|
|
|
78
130
|
return notFoundError("Agent", slug);
|
|
79
131
|
}
|
|
80
132
|
|
|
133
|
+
/**
|
|
134
|
+
* AuthorizeMemberAudience — the member-profile lane's gate, membership
|
|
135
|
+
* BEFORE existence: the Java AgentShareGetSharedProfileForMemberHandler
|
|
136
|
+
* order. getSharedProfileForMember is the signed-in resolution path for a
|
|
137
|
+
* share URL, and the proto pins its contract: a share that does not exist,
|
|
138
|
+
* is disabled, or is asked for by someone who is not a member of the
|
|
139
|
+
* sharing organization all answer the SAME NOT_FOUND, so a share URL
|
|
140
|
+
* teaches a non-member nothing — not even whether the share exists. A
|
|
141
|
+
* non-member resolving a public share uses the anonymous lane instead.
|
|
142
|
+
*
|
|
143
|
+
* The question is can_view on the organization named in the reference (the
|
|
144
|
+
* viewer set: members and above), asked live on every call so a revoked
|
|
145
|
+
* member loses access at once; the RPC is is_skip_authorization because
|
|
146
|
+
* the target is the reference's organization, not a request field the
|
|
147
|
+
* annotation can key on. This is deliberately NOT the shared
|
|
148
|
+
* AuthorizeResolvedTarget step: that step answers deny with
|
|
149
|
+
* PERMISSION_DENIED, and this lane's wire contract is the indistinguishable
|
|
150
|
+
* NOT_FOUND above, so the lane keeps its own mapping over the same
|
|
151
|
+
* evaluation (the decision form checkMyPermission uses). An empty org is
|
|
152
|
+
* left to the loader's INVALID_ARGUMENT, the proto's own copy for it; an
|
|
153
|
+
* unavailable authorizer is INTERNAL, never softened into a refusal; the
|
|
154
|
+
* `internal` class is exempt as everywhere.
|
|
155
|
+
*/
|
|
156
|
+
export function newAuthorizeMemberAudienceStep(
|
|
157
|
+
authorizer: Authorizer,
|
|
158
|
+
): PipelineStep<GetByReferenceDesc> {
|
|
159
|
+
return {
|
|
160
|
+
name: "AuthorizeMemberAudience",
|
|
161
|
+
async execute(ctx: RequestContext<GetByReferenceDesc>): Promise<void> {
|
|
162
|
+
const ref = ctx.input;
|
|
163
|
+
if (ref.org === "" || ctx.callerIdentity.callerClass === "internal") {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const decision = await evaluateAuthorizer(
|
|
167
|
+
authorizer,
|
|
168
|
+
ctx.callerIdentity,
|
|
169
|
+
{
|
|
170
|
+
permission: IamPermission.can_view,
|
|
171
|
+
resourceKind: ApiResourceKind.organization,
|
|
172
|
+
resourceId: ref.org,
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
switch (decision.kind) {
|
|
176
|
+
case "allow":
|
|
177
|
+
return;
|
|
178
|
+
case "deny":
|
|
179
|
+
case "not-found":
|
|
180
|
+
throw sharedNotFound(ref.slug);
|
|
181
|
+
case "unavailable":
|
|
182
|
+
throw internalError(
|
|
183
|
+
decision.cause,
|
|
184
|
+
AUTHORIZATION_UNAVAILABLE_MESSAGE,
|
|
185
|
+
);
|
|
186
|
+
default: {
|
|
187
|
+
const exhaustive: never = decision;
|
|
188
|
+
throw internalError(
|
|
189
|
+
new Error(`unknown decision ${JSON.stringify(exhaustive)}`),
|
|
190
|
+
AUTHORIZATION_UNAVAILABLE_MESSAGE,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
81
198
|
/**
|
|
82
199
|
* The link-token predicate — Go sharingLinkTokenAllowed, the mirror of the
|
|
83
200
|
* cloud edition's SharingLinkTokenPolicy:
|
|
@@ -90,7 +207,10 @@ export function sharedNotFound(slug: string): ConnectError {
|
|
|
90
207
|
* guard restores Go's semantics; the length of a token is not secret (all
|
|
91
208
|
* server-minted tokens are 27 chars).
|
|
92
209
|
*/
|
|
93
|
-
export function sharingLinkTokenAllowed(
|
|
210
|
+
export function sharingLinkTokenAllowed(
|
|
211
|
+
presented: string,
|
|
212
|
+
live: string,
|
|
213
|
+
): boolean {
|
|
94
214
|
if (live === "") {
|
|
95
215
|
return true;
|
|
96
216
|
}
|
|
@@ -174,15 +294,19 @@ export async function findShareByOrgAndSlug(
|
|
|
174
294
|
/**
|
|
175
295
|
* ResolveShareDefaults — Go resolveShareDefaultsStep:
|
|
176
296
|
* 1. Requires metadata.org (URL + billing identity, never inferred).
|
|
177
|
-
* 2. Normalizes spec.agent_ref.org (empty means same-org) and
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
297
|
+
* 2. Normalizes spec.agent_ref.org (empty means same-org) and refuses an
|
|
298
|
+
* agent_ref that names another organization (the module header) with
|
|
299
|
+
* the same-organization sentence, BEFORE any lookup, so the share
|
|
300
|
+
* lane never says whether another organization's slug exists.
|
|
301
|
+
* 3. Loads the referenced agent — a nonexistent agent is refused with
|
|
302
|
+
* the same NOT_FOUND a direct agent lookup would produce.
|
|
181
303
|
* 4. Defaults metadata.slug (and name) from the agent when the caller
|
|
182
304
|
* provided neither — the canonical share keeps the agent's hosted URL.
|
|
183
305
|
* Runs before ResolveSlug, which skips already-set slugs.
|
|
184
306
|
*/
|
|
185
|
-
export function newResolveShareDefaultsStep(
|
|
307
|
+
export function newResolveShareDefaultsStep(
|
|
308
|
+
store: Store,
|
|
309
|
+
): PipelineStep<AgentShareDesc> {
|
|
186
310
|
return {
|
|
187
311
|
name: "ResolveShareDefaults",
|
|
188
312
|
async execute(ctx: RequestContext<AgentShareDesc>): Promise<void> {
|
|
@@ -203,16 +327,19 @@ export function newResolveShareDefaultsStep(store: Store): PipelineStep<AgentSha
|
|
|
203
327
|
if (agentRef!.org === "") {
|
|
204
328
|
agentRef!.org = metadata!.org;
|
|
205
329
|
}
|
|
330
|
+
if (agentRef!.org !== metadata!.org) {
|
|
331
|
+
throw failedPreconditionError(sameOrgInvariantMessage(agentRef!.org));
|
|
332
|
+
}
|
|
206
333
|
|
|
207
|
-
const agent = await findAgentByOrgAndSlug(
|
|
334
|
+
const agent = await findAgentByOrgAndSlug(
|
|
335
|
+
store,
|
|
336
|
+
agentRef!.org,
|
|
337
|
+
agentRef!.slug,
|
|
338
|
+
);
|
|
208
339
|
if (agent === undefined) {
|
|
209
340
|
throw notFoundError("Agent", agentRef!.slug);
|
|
210
341
|
}
|
|
211
342
|
|
|
212
|
-
if (agentRef!.org !== metadata!.org) {
|
|
213
|
-
await validateCrossOrgShare(store, share, agent);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
343
|
ctx.set(REFERENCED_AGENT_KEY, agent);
|
|
217
344
|
|
|
218
345
|
// Canonical-share default: no slug and no name means "share this
|
|
@@ -226,118 +353,6 @@ export function newResolveShareDefaultsStep(store: Store): PipelineStep<AgentSha
|
|
|
226
353
|
};
|
|
227
354
|
}
|
|
228
355
|
|
|
229
|
-
/**
|
|
230
|
-
* The cross-org share contract (decision 013) — Go validateCrossOrgShare:
|
|
231
|
-
* - The agent must be marketplace-public; a non-public agent is refused
|
|
232
|
-
* with the same NOT_FOUND as a missing one (no existence probe for
|
|
233
|
-
* private slugs).
|
|
234
|
-
* - The audience must be public — org-audience semantics don't carry
|
|
235
|
-
* across the org boundary.
|
|
236
|
-
* - Every declared dependency must itself be public; the refusal names
|
|
237
|
-
* every blocker (sorted) so the sharing org knows exactly what to ask
|
|
238
|
-
* the agent's org to publish.
|
|
239
|
-
* Runtime re-enforcement is cloud-side; this create-time sweep is the
|
|
240
|
-
* fail-loud half, mirrored in both editions.
|
|
241
|
-
*/
|
|
242
|
-
async function validateCrossOrgShare(
|
|
243
|
-
store: Store,
|
|
244
|
-
share: AgentShare,
|
|
245
|
-
agent: Agent,
|
|
246
|
-
): Promise<void> {
|
|
247
|
-
const agentMeta = agent.metadata;
|
|
248
|
-
|
|
249
|
-
if (agentMeta?.visibility !== ApiResourceVisibility.visibility_public) {
|
|
250
|
-
throw notFoundError("Agent", agentMeta?.slug ?? "");
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// protobuf-es strips the shared enum prefix: proto
|
|
254
|
-
// agent_share_audience_org generates as AgentShareAudience.org.
|
|
255
|
-
if (share.spec?.audience === AgentShareAudience.org) {
|
|
256
|
-
throw failedPreconditionError(crossOrgAudienceMessage(agentMeta.org));
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const blockers = await findNonPublicDependencies(store, agent);
|
|
260
|
-
if (blockers.length > 0) {
|
|
261
|
-
throw failedPreconditionError(
|
|
262
|
-
crossOrgBlockersMessage(agentMeta.org, agentMeta.slug, blockers),
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Sweeps the agent's declared blueprint dependencies — skill_refs
|
|
269
|
-
* (including every sub-agent's) and mcp_server_usages — and returns a
|
|
270
|
-
* deterministic "kind org/slug" entry for each that is missing or not
|
|
271
|
-
* visibility_public — Go findNonPublicDependencies. A reference with an
|
|
272
|
-
* empty org is relative to the AGENT's org (defensive parity with the
|
|
273
|
-
* cloud edition's referenceMatches; agent writes normalize refs to
|
|
274
|
-
* absolute form).
|
|
275
|
-
*/
|
|
276
|
-
async function findNonPublicDependencies(
|
|
277
|
-
store: Store,
|
|
278
|
-
agent: Agent,
|
|
279
|
-
): Promise<string[]> {
|
|
280
|
-
const spec = agent.spec;
|
|
281
|
-
const agentOrg = agent.metadata?.org ?? "";
|
|
282
|
-
|
|
283
|
-
interface DepRef {
|
|
284
|
-
kind: ApiResourceKind;
|
|
285
|
-
org: string;
|
|
286
|
-
slug: string;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const seen = new Set<string>();
|
|
290
|
-
const deps: DepRef[] = [];
|
|
291
|
-
const add = (kind: ApiResourceKind, ref: ApiResourceReference | undefined): void => {
|
|
292
|
-
if (ref === undefined || ref.slug === "") {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
const org = ref.org !== "" ? ref.org : agentOrg;
|
|
296
|
-
const key = `${kind}|${org}|${ref.slug}`;
|
|
297
|
-
if (!seen.has(key)) {
|
|
298
|
-
seen.add(key);
|
|
299
|
-
deps.push({ kind, org, slug: ref.slug });
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
for (const ref of spec?.skillRefs ?? []) {
|
|
304
|
-
add(ApiResourceKind.skill, ref);
|
|
305
|
-
}
|
|
306
|
-
for (const sub of spec?.subAgents ?? []) {
|
|
307
|
-
for (const ref of sub.skillRefs) {
|
|
308
|
-
add(ApiResourceKind.skill, ref);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
for (const usage of spec?.mcpServerUsages ?? []) {
|
|
312
|
-
add(ApiResourceKind.mcp_server, usage.mcpServerRef);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const blockers: string[] = [];
|
|
316
|
-
for (const dep of deps) {
|
|
317
|
-
let visibility: ApiResourceVisibility | undefined;
|
|
318
|
-
try {
|
|
319
|
-
// Per-kind resolution, exactly Go's switch — skill and mcp_server
|
|
320
|
-
// are the only dependency kinds an agent blueprint declares.
|
|
321
|
-
const resolved =
|
|
322
|
-
dep.kind === ApiResourceKind.skill
|
|
323
|
-
? await findResourceBySlug(store, dep.kind, SkillSchema, dep.slug, dep.org)
|
|
324
|
-
: await findResourceBySlug(store, dep.kind, McpServerSchema, dep.slug, dep.org);
|
|
325
|
-
visibility = resolved?.metadata?.visibility;
|
|
326
|
-
} catch (error) {
|
|
327
|
-
throw internalError(
|
|
328
|
-
error,
|
|
329
|
-
`failed to resolve ${ApiResourceKind[dep.kind]} ${dep.org}/${dep.slug} while validating cross-org share`,
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
if (visibility !== ApiResourceVisibility.visibility_public) {
|
|
333
|
-
blockers.push(`${ApiResourceKind[dep.kind]} ${dep.org}/${dep.slug}`);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
blockers.sort();
|
|
338
|
-
return blockers;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
356
|
/**
|
|
342
357
|
* StampAgentPin — Go stampAgentPinStep: writes status.agent_id, the
|
|
343
358
|
* server-owned rebind pin (decision 013). agent_ref is org+slug and slugs
|
|
@@ -371,10 +386,8 @@ export function newStampAgentPinStep(): PipelineStep<AgentShareDesc> {
|
|
|
371
386
|
|
|
372
387
|
/**
|
|
373
388
|
* ValidateShareUpdate — Go validateShareUpdateStep: spec.agent_ref must
|
|
374
|
-
* keep referencing the same agent
|
|
375
|
-
*
|
|
376
|
-
* open a side door to an org-audience cross-org share). Runs after
|
|
377
|
-
* LoadExisting. metadata.slug/org immutability needs no step — the generic
|
|
389
|
+
* keep referencing the same agent. Runs after LoadExisting.
|
|
390
|
+
* metadata.slug/org immutability needs no step — the generic
|
|
378
391
|
* BuildUpdateState preserves both, and status (including the pin and link
|
|
379
392
|
* token) wholesale.
|
|
380
393
|
*/
|
|
@@ -396,21 +409,21 @@ export function newValidateShareUpdateStep(): PipelineStep<AgentShareDesc> {
|
|
|
396
409
|
// Normalize the input ref's org the same way create does (empty
|
|
397
410
|
// means the share's own org) before comparing.
|
|
398
411
|
const inputOrg =
|
|
399
|
-
(inputRef?.org ?? "") !== ""
|
|
412
|
+
(inputRef?.org ?? "") !== ""
|
|
413
|
+
? inputRef!.org
|
|
414
|
+
: (existing.metadata?.org ?? "");
|
|
400
415
|
|
|
401
416
|
if (
|
|
402
417
|
(inputRef?.slug ?? "") !== (existingRef?.slug ?? "") ||
|
|
403
418
|
inputOrg !== (existingRef?.org ?? "")
|
|
404
419
|
) {
|
|
405
420
|
throw failedPreconditionError(
|
|
406
|
-
agentRefImmutableMessage(
|
|
421
|
+
agentRefImmutableMessage(
|
|
422
|
+
existingRef?.org ?? "",
|
|
423
|
+
existingRef?.slug ?? "",
|
|
424
|
+
),
|
|
407
425
|
);
|
|
408
426
|
}
|
|
409
|
-
|
|
410
|
-
const isCrossOrg = (existingRef?.org ?? "") !== (existing.metadata?.org ?? "");
|
|
411
|
-
if (isCrossOrg && ctx.input.spec?.audience === AgentShareAudience.org) {
|
|
412
|
-
throw failedPreconditionError(crossOrgAudienceMessage(existingRef?.org ?? ""));
|
|
413
|
-
}
|
|
414
427
|
},
|
|
415
428
|
};
|
|
416
429
|
}
|
|
@@ -422,15 +435,19 @@ export function newValidateShareUpdateStep(): PipelineStep<AgentShareDesc> {
|
|
|
422
435
|
* SHARE; display fields and default_instance_id from the AGENT. Three
|
|
423
436
|
* misses all fail closed with the uniform refusal, indistinguishable from
|
|
424
437
|
* absence: a dangling agent_ref, a stale agent-id pin (the rebind guard),
|
|
425
|
-
* and
|
|
426
|
-
*
|
|
438
|
+
* and an agent in another organization (a share written before the
|
|
439
|
+
* same-organization invariant; this release serves no such share).
|
|
427
440
|
*/
|
|
428
441
|
export async function buildSharedAgentProfile(
|
|
429
442
|
store: Store,
|
|
430
443
|
share: AgentShare,
|
|
431
444
|
): Promise<SharedAgentProfile> {
|
|
432
445
|
const ref = share.spec?.agentRef;
|
|
433
|
-
const agent = await findAgentByOrgAndSlug(
|
|
446
|
+
const agent = await findAgentByOrgAndSlug(
|
|
447
|
+
store,
|
|
448
|
+
ref?.org ?? "",
|
|
449
|
+
ref?.slug ?? "",
|
|
450
|
+
);
|
|
434
451
|
if (agent === undefined) {
|
|
435
452
|
throw sharedNotFound(share.metadata?.slug ?? "");
|
|
436
453
|
}
|
|
@@ -440,11 +457,7 @@ export async function buildSharedAgentProfile(
|
|
|
440
457
|
throw sharedNotFound(share.metadata?.slug ?? "");
|
|
441
458
|
}
|
|
442
459
|
|
|
443
|
-
|
|
444
|
-
if (
|
|
445
|
-
isCrossOrg &&
|
|
446
|
-
agent.metadata?.visibility !== ApiResourceVisibility.visibility_public
|
|
447
|
-
) {
|
|
460
|
+
if ((share.metadata?.org ?? "") !== (agent.metadata?.org ?? "")) {
|
|
448
461
|
throw sharedNotFound(share.metadata?.slug ?? "");
|
|
449
462
|
}
|
|
450
463
|
|
|
@@ -66,9 +66,9 @@ import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
|
|
|
66
66
|
import { RequestContext } from "../../pipeline/request-context.js";
|
|
67
67
|
import {
|
|
68
68
|
authorizeDirect,
|
|
69
|
-
authorizeResolvedResource,
|
|
70
69
|
newAuthorizeStep,
|
|
71
70
|
} from "../../pipeline/steps/authorize.js";
|
|
71
|
+
import { newAuthorizeResolvedTargetStep } from "../../pipeline/steps/authorize-resolved-target.js";
|
|
72
72
|
import {
|
|
73
73
|
generateId,
|
|
74
74
|
setAuditFieldsForCreate,
|
|
@@ -426,23 +426,18 @@ async function listByExecution(
|
|
|
426
426
|
}
|
|
427
427
|
},
|
|
428
428
|
})
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
// divergence from Java's deny-everyone arm on this lane.
|
|
442
|
-
const input = stepCtx.input;
|
|
443
|
-
await authorizeResolvedResource(
|
|
444
|
-
deps.authorizer,
|
|
445
|
-
stepCtx.callerIdentity,
|
|
429
|
+
// The Java ArtifactListByExecutionHandler's gate: can_view on the PARENT
|
|
430
|
+
// execution — "if you can view an execution, you can list its
|
|
431
|
+
// artifacts." The two-field dispatch (workflow-execution first, the Java
|
|
432
|
+
// order) is why the declarative annotation cannot express this lane and
|
|
433
|
+
// the proto carries is_skip_authorization. Deny copy is the Java
|
|
434
|
+
// handler's byte-pinned error_msg; a nonexistent id answers NOT_FOUND
|
|
435
|
+
// through the authorizer's probe — the ruled uniform unknown-id
|
|
436
|
+
// posture, a recorded divergence from Java's deny-everyone arm here.
|
|
437
|
+
.addStep(
|
|
438
|
+
newAuthorizeResolvedTargetStep(
|
|
439
|
+
deps.authorizer,
|
|
440
|
+
({ input }) => [
|
|
446
441
|
{
|
|
447
442
|
permission: IamPermission.can_view,
|
|
448
443
|
resourceKind:
|
|
@@ -453,11 +448,12 @@ async function listByExecution(
|
|
|
453
448
|
input.workflowExecutionId !== ""
|
|
454
449
|
? input.workflowExecutionId
|
|
455
450
|
: input.agentExecutionId,
|
|
451
|
+
deniedMessage: "unauthorized to list artifacts for this execution",
|
|
456
452
|
},
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
453
|
+
],
|
|
454
|
+
"AuthorizeParentExecution",
|
|
455
|
+
),
|
|
456
|
+
)
|
|
461
457
|
.addStep({
|
|
462
458
|
name: "QueryArtifactsByExecution",
|
|
463
459
|
async execute(stepCtx): Promise<void> {
|
|
@@ -51,6 +51,10 @@ import type { PipelineStep } from "../../pipeline/pipeline.js";
|
|
|
51
51
|
import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
|
|
52
52
|
import { RequestContext } from "../../pipeline/request-context.js";
|
|
53
53
|
import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
|
|
54
|
+
import {
|
|
55
|
+
loadedTargetAsMethod,
|
|
56
|
+
newAuthorizeResolvedTargetStep,
|
|
57
|
+
} from "../../pipeline/steps/authorize-resolved-target.js";
|
|
54
58
|
import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
|
|
55
59
|
import { newBuildNewStateStep } from "../../pipeline/steps/defaults.js";
|
|
56
60
|
import { newBuildUpdateStateStep } from "../../pipeline/steps/build-update-state.js";
|
|
@@ -369,6 +373,12 @@ async function getByReference(
|
|
|
369
373
|
)
|
|
370
374
|
.addStep(newValidateProtoStep())
|
|
371
375
|
.addStep(newLoadByReferenceStep(deps.store, ChannelAppSchema))
|
|
376
|
+
.addStep(
|
|
377
|
+
newAuthorizeResolvedTargetStep(
|
|
378
|
+
deps.authorizer,
|
|
379
|
+
loadedTargetAsMethod(ChannelAppQueryController.method.get),
|
|
380
|
+
),
|
|
381
|
+
)
|
|
372
382
|
.build()
|
|
373
383
|
.execute(reqCtx);
|
|
374
384
|
const app = reqCtx.get(TARGET_RESOURCE_KEY) as ChannelApp;
|
|
@@ -58,8 +58,11 @@ import type { PipelineStep } from "../../pipeline/pipeline.js";
|
|
|
58
58
|
import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
|
|
59
59
|
import { RequestContext } from "../../pipeline/request-context.js";
|
|
60
60
|
import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
|
|
61
|
+
import {
|
|
62
|
+
loadedTargetAsMethod,
|
|
63
|
+
newAuthorizeResolvedTargetStep,
|
|
64
|
+
} from "../../pipeline/steps/authorize-resolved-target.js";
|
|
61
65
|
import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
|
|
62
|
-
import { newAuthorizeVisibilityTransitionStep } from "../../pipeline/steps/visibility-gates.js";
|
|
63
66
|
import {
|
|
64
67
|
newBuildNewStateStep,
|
|
65
68
|
setAuditFieldsForUpdate,
|
|
@@ -93,7 +96,10 @@ import {
|
|
|
93
96
|
TARGET_RESOURCE_KEY,
|
|
94
97
|
newLoadTargetStep,
|
|
95
98
|
} from "../../pipeline/steps/load-target.js";
|
|
96
|
-
import {
|
|
99
|
+
import {
|
|
100
|
+
newNormalizeReferencesStep,
|
|
101
|
+
newValidateReferencesStep,
|
|
102
|
+
} from "../../pipeline/steps/references.js";
|
|
97
103
|
import {
|
|
98
104
|
newCleanupIamPoliciesStep,
|
|
99
105
|
newCreateAuthorizationTuplesStep,
|
|
@@ -240,6 +246,7 @@ async function update(
|
|
|
240
246
|
.addStep(newPreserveRedactedSecretsStep())
|
|
241
247
|
.addStep(newEncryptSecretValuesStep(deps.secretService, deps.logger))
|
|
242
248
|
.addStep(newNormalizeReferencesStep())
|
|
249
|
+
.addStep(newValidateReferencesStep(deps.store))
|
|
243
250
|
.addStep(newPersistStep(deps.store))
|
|
244
251
|
.addStep(
|
|
245
252
|
newDestroyDroppedEnvironmentSecretsStep(deps.secretService, deps.logger),
|
|
@@ -394,12 +401,6 @@ async function updateVisibility(
|
|
|
394
401
|
// After load, per the cross-edition error precedence: unknown id +
|
|
395
402
|
// bad level = NOT_FOUND on both editions.
|
|
396
403
|
.addStep(newValidateVisibilityUpdateStep())
|
|
397
|
-
.addStep(
|
|
398
|
-
newAuthorizeVisibilityTransitionStep(
|
|
399
|
-
UPDATE_VISIBILITY_ENVIRONMENT_KEY,
|
|
400
|
-
deps.authorizer,
|
|
401
|
-
),
|
|
402
|
-
)
|
|
403
404
|
.addStep(newValidateEnvironmentShareRestrictionStep())
|
|
404
405
|
.addStep(newSetEnvironmentVisibilityStep())
|
|
405
406
|
.addStep(newPersistEnvironmentForVisibilityUpdateStep(deps.store))
|
|
@@ -682,6 +683,12 @@ async function getByReference(
|
|
|
682
683
|
)
|
|
683
684
|
.addStep(newValidateProtoStep())
|
|
684
685
|
.addStep(newLoadByReferenceStep(deps.store, EnvironmentSchema))
|
|
686
|
+
.addStep(
|
|
687
|
+
newAuthorizeResolvedTargetStep(
|
|
688
|
+
deps.authorizer,
|
|
689
|
+
loadedTargetAsMethod(EnvironmentQueryController.method.get),
|
|
690
|
+
),
|
|
691
|
+
)
|
|
685
692
|
.build()
|
|
686
693
|
.execute(reqCtx);
|
|
687
694
|
const env = reqCtx.get(TARGET_RESOURCE_KEY) as Environment;
|
|
@@ -56,6 +56,10 @@ import { newPipeline } from "../../pipeline/pipeline.js";
|
|
|
56
56
|
import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
|
|
57
57
|
import { RequestContext } from "../../pipeline/request-context.js";
|
|
58
58
|
import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
|
|
59
|
+
import {
|
|
60
|
+
loadedTargetAsMethod,
|
|
61
|
+
newAuthorizeResolvedTargetStep,
|
|
62
|
+
} from "../../pipeline/steps/authorize-resolved-target.js";
|
|
59
63
|
import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
|
|
60
64
|
import { newBuildNewStateStep } from "../../pipeline/steps/defaults.js";
|
|
61
65
|
import {
|
|
@@ -78,7 +82,10 @@ import {
|
|
|
78
82
|
TARGET_RESOURCE_KEY,
|
|
79
83
|
newLoadTargetStep,
|
|
80
84
|
} from "../../pipeline/steps/load-target.js";
|
|
81
|
-
import {
|
|
85
|
+
import {
|
|
86
|
+
newNormalizeReferencesStep,
|
|
87
|
+
newValidateReferencesStep,
|
|
88
|
+
} from "../../pipeline/steps/references.js";
|
|
82
89
|
import {
|
|
83
90
|
newCleanupIamPoliciesStep,
|
|
84
91
|
newCreateAuthorizationTuplesStep,
|
|
@@ -182,6 +189,7 @@ async function createExecutionContext(
|
|
|
182
189
|
.addStep(newBuildNewStateStep())
|
|
183
190
|
.addStep(newGuardReservedLabelsStep(deps.authorizer))
|
|
184
191
|
.addStep(newNormalizeReferencesStep())
|
|
192
|
+
.addStep(newValidateReferencesStep(deps.store))
|
|
185
193
|
.addStep(newEncryptSecretValuesStep(deps.secretService, deps.logger))
|
|
186
194
|
.addStep(newPersistStep(deps.store))
|
|
187
195
|
.addStep(
|
|
@@ -361,6 +369,12 @@ async function getByReference(
|
|
|
361
369
|
)
|
|
362
370
|
.addStep(newValidateProtoStep())
|
|
363
371
|
.addStep(newLoadByReferenceStep(deps.store, ExecutionContextSchema))
|
|
372
|
+
.addStep(
|
|
373
|
+
newAuthorizeResolvedTargetStep(
|
|
374
|
+
deps.authorizer,
|
|
375
|
+
loadedTargetAsMethod(ExecutionContextQueryController.method.get),
|
|
376
|
+
),
|
|
377
|
+
)
|
|
364
378
|
.build()
|
|
365
379
|
.execute(reqCtx);
|
|
366
380
|
const ec = reqCtx.get(TARGET_RESOURCE_KEY) as ExecutionContext;
|
|
@@ -34,6 +34,7 @@ import { isCiphertextShaped } from "../../encryption/encryption.js";
|
|
|
34
34
|
import type { SecretService } from "../../encryption/encryption.js";
|
|
35
35
|
import { EncryptionScope } from "../../encryption/encryption.js";
|
|
36
36
|
import type { Authorizer, AuthzDecision } from "../../extensions/authorizer.js";
|
|
37
|
+
import { isServerComposedRequest } from "../../extensions/identity.js";
|
|
37
38
|
import {
|
|
38
39
|
internalError,
|
|
39
40
|
invalidArgumentError,
|
|
@@ -240,7 +241,7 @@ export function newAuthorizeExecutionContextCreateStep(
|
|
|
240
241
|
ctx: RequestContext<typeof ExecutionContextSchema>,
|
|
241
242
|
): Promise<void> {
|
|
242
243
|
const caller = ctx.callerIdentity;
|
|
243
|
-
if (caller
|
|
244
|
+
if (isServerComposedRequest(caller)) {
|
|
244
245
|
return; // authorized upstream — the Java in-process trust arm
|
|
245
246
|
}
|
|
246
247
|
let decision: AuthzDecision;
|