@stigmer/server 3.15.3-dev.20260914121148 → 3.16.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/README.md +3 -3
- package/dist/archive/content-store.d.ts +35 -0
- package/dist/archive/content-store.d.ts.map +1 -0
- package/dist/archive/content-store.js +98 -0
- package/dist/archive/content-store.js.map +1 -0
- package/dist/archive/inflate.d.ts +22 -0
- package/dist/archive/inflate.d.ts.map +1 -0
- package/dist/archive/inflate.js +75 -0
- package/dist/archive/inflate.js.map +1 -0
- package/dist/archive/limits.d.ts +33 -0
- package/dist/archive/limits.d.ts.map +1 -0
- package/dist/archive/limits.js +31 -0
- package/dist/archive/limits.js.map +1 -0
- package/dist/archive/open.d.ts +24 -0
- package/dist/archive/open.d.ts.map +1 -0
- package/dist/archive/open.js +93 -0
- package/dist/archive/open.js.map +1 -0
- package/dist/{domain/skill/storage → archive}/prefilter.d.ts +5 -0
- package/dist/archive/prefilter.d.ts.map +1 -0
- package/dist/archive/prefilter.js.map +1 -0
- package/dist/archive/write.d.ts +8 -0
- package/dist/archive/write.d.ts.map +1 -0
- package/dist/archive/write.js +44 -0
- package/dist/archive/write.js.map +1 -0
- package/dist/authorization/authorizer.d.ts +98 -0
- package/dist/authorization/authorizer.d.ts.map +1 -0
- package/dist/authorization/authorizer.js +156 -0
- package/dist/authorization/authorizer.js.map +1 -0
- package/dist/authorization/derived-tuples.d.ts +42 -0
- package/dist/authorization/derived-tuples.d.ts.map +1 -0
- package/dist/authorization/derived-tuples.js +240 -0
- package/dist/authorization/derived-tuples.js.map +1 -0
- package/dist/authorization/evaluator.d.ts +66 -0
- package/dist/authorization/evaluator.d.ts.map +1 -0
- package/dist/authorization/evaluator.js +153 -0
- package/dist/authorization/evaluator.js.map +1 -0
- package/dist/authorization/facts.d.ts +29 -0
- package/dist/authorization/facts.d.ts.map +1 -0
- package/dist/authorization/facts.js +17 -0
- package/dist/authorization/facts.js.map +1 -0
- package/dist/authorization/lane-admission.d.ts +50 -0
- package/dist/authorization/lane-admission.d.ts.map +1 -0
- package/dist/authorization/lane-admission.js +13 -0
- package/dist/authorization/lane-admission.js.map +1 -0
- package/dist/authorization/list-read-scope.d.ts +18 -0
- package/dist/authorization/list-read-scope.d.ts.map +1 -0
- package/dist/authorization/list-read-scope.js +155 -0
- package/dist/authorization/list-read-scope.js.map +1 -0
- package/dist/authorization/model/agent.d.ts +2 -0
- package/dist/authorization/model/agent.d.ts.map +1 -0
- package/dist/authorization/model/agent.js +42 -0
- package/dist/authorization/model/agent.js.map +1 -0
- package/dist/authorization/model/agent_channel.d.ts +2 -0
- package/dist/authorization/model/agent_channel.d.ts.map +1 -0
- package/dist/authorization/model/agent_channel.js +38 -0
- package/dist/authorization/model/agent_channel.js.map +1 -0
- package/dist/authorization/model/agent_execution.d.ts +2 -0
- package/dist/authorization/model/agent_execution.d.ts.map +1 -0
- package/dist/authorization/model/agent_execution.js +25 -0
- package/dist/authorization/model/agent_execution.js.map +1 -0
- package/dist/authorization/model/agent_instance.d.ts +2 -0
- package/dist/authorization/model/agent_instance.d.ts.map +1 -0
- package/dist/authorization/model/agent_instance.js +47 -0
- package/dist/authorization/model/agent_instance.js.map +1 -0
- package/dist/authorization/model/agent_share.d.ts +2 -0
- package/dist/authorization/model/agent_share.d.ts.map +1 -0
- package/dist/authorization/model/agent_share.js +29 -0
- package/dist/authorization/model/agent_share.js.map +1 -0
- package/dist/authorization/model/api_key.d.ts +2 -0
- package/dist/authorization/model/api_key.d.ts.map +1 -0
- package/dist/authorization/model/api_key.js +27 -0
- package/dist/authorization/model/api_key.js.map +1 -0
- package/dist/authorization/model/artifact.d.ts +2 -0
- package/dist/authorization/model/artifact.d.ts.map +1 -0
- package/dist/authorization/model/artifact.js +27 -0
- package/dist/authorization/model/artifact.js.map +1 -0
- package/dist/authorization/model/channel_app.d.ts +2 -0
- package/dist/authorization/model/channel_app.d.ts.map +1 -0
- package/dist/authorization/model/channel_app.js +28 -0
- package/dist/authorization/model/channel_app.js.map +1 -0
- package/dist/authorization/model/default-of.d.ts +38 -0
- package/dist/authorization/model/default-of.d.ts.map +1 -0
- package/dist/authorization/model/default-of.js +39 -0
- package/dist/authorization/model/default-of.js.map +1 -0
- package/dist/authorization/model/environment.d.ts +2 -0
- package/dist/authorization/model/environment.d.ts.map +1 -0
- package/dist/authorization/model/environment.js +33 -0
- package/dist/authorization/model/environment.js.map +1 -0
- package/dist/authorization/model/execution_context.d.ts +2 -0
- package/dist/authorization/model/execution_context.d.ts.map +1 -0
- package/dist/authorization/model/execution_context.js +19 -0
- package/dist/authorization/model/execution_context.js.map +1 -0
- package/dist/authorization/model/iam_policy.d.ts +2 -0
- package/dist/authorization/model/iam_policy.d.ts.map +1 -0
- package/dist/authorization/model/iam_policy.js +31 -0
- package/dist/authorization/model/iam_policy.js.map +1 -0
- package/dist/authorization/model/identity_account.d.ts +2 -0
- package/dist/authorization/model/identity_account.d.ts.map +1 -0
- package/dist/authorization/model/identity_account.js +25 -0
- package/dist/authorization/model/identity_account.js.map +1 -0
- package/dist/authorization/model/index.d.ts +36 -0
- package/dist/authorization/model/index.d.ts.map +1 -0
- package/dist/authorization/model/index.js +72 -0
- package/dist/authorization/model/index.js.map +1 -0
- package/dist/authorization/model/mcp_server.d.ts +2 -0
- package/dist/authorization/model/mcp_server.d.ts.map +1 -0
- package/dist/authorization/model/mcp_server.js +37 -0
- package/dist/authorization/model/mcp_server.js.map +1 -0
- package/dist/authorization/model/memory.d.ts +2 -0
- package/dist/authorization/model/memory.d.ts.map +1 -0
- package/dist/authorization/model/memory.js +26 -0
- package/dist/authorization/model/memory.js.map +1 -0
- package/dist/authorization/model/oauth_app.d.ts +2 -0
- package/dist/authorization/model/oauth_app.d.ts.map +1 -0
- package/dist/authorization/model/oauth_app.js +30 -0
- package/dist/authorization/model/oauth_app.js.map +1 -0
- package/dist/authorization/model/organization.d.ts +2 -0
- package/dist/authorization/model/organization.d.ts.map +1 -0
- package/dist/authorization/model/organization.js +54 -0
- package/dist/authorization/model/organization.js.map +1 -0
- package/dist/authorization/model/plugin.d.ts +2 -0
- package/dist/authorization/model/plugin.d.ts.map +1 -0
- package/dist/authorization/model/plugin.js +44 -0
- package/dist/authorization/model/plugin.js.map +1 -0
- package/dist/authorization/model/project.d.ts +2 -0
- package/dist/authorization/model/project.d.ts.map +1 -0
- package/dist/authorization/model/project.js +32 -0
- package/dist/authorization/model/project.js.map +1 -0
- package/dist/authorization/model/rewrite.d.ts +127 -0
- package/dist/authorization/model/rewrite.d.ts.map +1 -0
- package/dist/authorization/model/rewrite.js +82 -0
- package/dist/authorization/model/rewrite.js.map +1 -0
- package/dist/authorization/model/schedule.d.ts +2 -0
- package/dist/authorization/model/schedule.d.ts.map +1 -0
- package/dist/authorization/model/schedule.js +29 -0
- package/dist/authorization/model/schedule.js.map +1 -0
- package/dist/authorization/model/session.d.ts +2 -0
- package/dist/authorization/model/session.d.ts.map +1 -0
- package/dist/authorization/model/session.js +38 -0
- package/dist/authorization/model/session.js.map +1 -0
- package/dist/authorization/model/skill.d.ts +2 -0
- package/dist/authorization/model/skill.d.ts.map +1 -0
- package/dist/authorization/model/skill.js +38 -0
- package/dist/authorization/model/skill.js.map +1 -0
- package/dist/authorization/model/workflow.d.ts +2 -0
- package/dist/authorization/model/workflow.d.ts.map +1 -0
- package/dist/authorization/model/workflow.js +38 -0
- package/dist/authorization/model/workflow.js.map +1 -0
- package/dist/authorization/model/workflow_execution.d.ts +2 -0
- package/dist/authorization/model/workflow_execution.d.ts.map +1 -0
- package/dist/authorization/model/workflow_execution.js +32 -0
- package/dist/authorization/model/workflow_execution.js.map +1 -0
- package/dist/authorization/model/workflow_instance.d.ts +2 -0
- package/dist/authorization/model/workflow_instance.d.ts.map +1 -0
- package/dist/authorization/model/workflow_instance.js +92 -0
- package/dist/authorization/model/workflow_instance.js.map +1 -0
- package/dist/authorization/organization-directory.d.ts +13 -0
- package/dist/authorization/organization-directory.d.ts.map +1 -0
- package/dist/authorization/organization-directory.js +83 -0
- package/dist/authorization/organization-directory.js.map +1 -0
- package/dist/authorization/person.d.ts +42 -0
- package/dist/authorization/person.d.ts.map +1 -0
- package/dist/authorization/person.js +19 -0
- package/dist/authorization/person.js.map +1 -0
- package/dist/authorization/posture.d.ts +38 -0
- package/dist/authorization/posture.d.ts.map +1 -0
- package/dist/authorization/posture.js +7 -0
- package/dist/authorization/posture.js.map +1 -0
- package/dist/authorization/schedule-fire-caller.d.ts +12 -0
- package/dist/authorization/schedule-fire-caller.d.ts.map +1 -0
- package/dist/authorization/schedule-fire-caller.js +67 -0
- package/dist/authorization/schedule-fire-caller.js.map +1 -0
- package/dist/authorization/store-test-kit.d.ts +68 -0
- package/dist/authorization/store-test-kit.d.ts.map +1 -0
- package/dist/authorization/store-test-kit.js +311 -0
- package/dist/authorization/store-test-kit.js.map +1 -0
- package/dist/authorization/tuples.d.ts +115 -0
- package/dist/authorization/tuples.d.ts.map +1 -0
- package/dist/authorization/tuples.js +83 -0
- package/dist/authorization/tuples.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +220 -43
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/inprocess.d.ts +12 -0
- package/dist/boot/inprocess.d.ts.map +1 -1
- package/dist/boot/inprocess.js +68 -21
- package/dist/boot/inprocess.js.map +1 -1
- package/dist/domain/agent/controller.d.ts.map +1 -1
- package/dist/domain/agent/controller.js +9 -0
- package/dist/domain/agent/controller.js.map +1 -1
- package/dist/domain/executioncontext/resolve-values-for-caller.d.ts +33 -14
- package/dist/domain/executioncontext/resolve-values-for-caller.d.ts.map +1 -1
- package/dist/domain/executioncontext/resolve-values-for-caller.js +32 -8
- package/dist/domain/executioncontext/resolve-values-for-caller.js.map +1 -1
- package/dist/domain/iampolicy/constants.d.ts +11 -0
- package/dist/domain/iampolicy/constants.d.ts.map +1 -1
- package/dist/domain/iampolicy/constants.js +11 -0
- package/dist/domain/iampolicy/constants.js.map +1 -1
- package/dist/domain/iampolicy/membership.d.ts +72 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +141 -56
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/actor.d.ts +41 -0
- package/dist/domain/identityaccount/actor.d.ts.map +1 -0
- package/dist/domain/identityaccount/actor.js +34 -0
- package/dist/domain/identityaccount/actor.js.map +1 -0
- package/dist/domain/identityaccount/resolve.d.ts +19 -0
- package/dist/domain/identityaccount/resolve.d.ts.map +1 -1
- package/dist/domain/identityaccount/resolve.js +12 -0
- package/dist/domain/identityaccount/resolve.js.map +1 -1
- package/dist/domain/mcpserver/connect-execution-id.d.ts +5 -0
- package/dist/domain/mcpserver/connect-execution-id.d.ts.map +1 -0
- package/dist/domain/mcpserver/connect-execution-id.js +32 -0
- package/dist/domain/mcpserver/connect-execution-id.js.map +1 -0
- package/dist/domain/mcpserver/connect.d.ts +28 -2
- package/dist/domain/mcpserver/connect.d.ts.map +1 -1
- package/dist/domain/mcpserver/connect.js +27 -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 +9 -0
- package/dist/domain/mcpserver/controller.js.map +1 -1
- package/dist/domain/mcpserver/engine.d.ts +9 -3
- 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.js +1 -1
- package/dist/domain/mcpserver/start-connect.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +24 -11
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/plugin/archive.d.ts +37 -0
- package/dist/domain/plugin/archive.d.ts.map +1 -0
- package/dist/domain/plugin/archive.js +50 -0
- package/dist/domain/plugin/archive.js.map +1 -0
- package/dist/domain/plugin/constants.d.ts +38 -0
- package/dist/domain/plugin/constants.d.ts.map +1 -0
- package/dist/domain/plugin/constants.js +46 -0
- package/dist/domain/plugin/constants.js.map +1 -0
- package/dist/domain/plugin/controller.d.ts +25 -0
- package/dist/domain/plugin/controller.d.ts.map +1 -0
- package/dist/domain/plugin/controller.js +493 -0
- package/dist/domain/plugin/controller.js.map +1 -0
- package/dist/domain/plugin/materialize/agent.d.ts +13 -0
- package/dist/domain/plugin/materialize/agent.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/agent.js +128 -0
- package/dist/domain/plugin/materialize/agent.js.map +1 -0
- package/dist/domain/plugin/materialize/default-agent-instructions.d.ts +22 -0
- package/dist/domain/plugin/materialize/default-agent-instructions.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/default-agent-instructions.js +31 -0
- package/dist/domain/plugin/materialize/default-agent-instructions.js.map +1 -0
- package/dist/domain/plugin/materialize/identity.d.ts +28 -0
- package/dist/domain/plugin/materialize/identity.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/identity.js +40 -0
- package/dist/domain/plugin/materialize/identity.js.map +1 -0
- package/dist/domain/plugin/materialize/mcp-servers.d.ts +15 -0
- package/dist/domain/plugin/materialize/mcp-servers.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/mcp-servers.js +131 -0
- package/dist/domain/plugin/materialize/mcp-servers.js.map +1 -0
- package/dist/domain/plugin/materialize/plan.d.ts +24 -0
- package/dist/domain/plugin/materialize/plan.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/plan.js +77 -0
- package/dist/domain/plugin/materialize/plan.js.map +1 -0
- package/dist/domain/plugin/materialize/ports.d.ts +42 -0
- package/dist/domain/plugin/materialize/ports.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/ports.js +2 -0
- package/dist/domain/plugin/materialize/ports.js.map +1 -0
- package/dist/domain/plugin/materialize/skills.d.ts +12 -0
- package/dist/domain/plugin/materialize/skills.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/skills.js +44 -0
- package/dist/domain/plugin/materialize/skills.js.map +1 -0
- package/dist/domain/plugin/materialize/workflows.d.ts +15 -0
- package/dist/domain/plugin/materialize/workflows.d.ts.map +1 -0
- package/dist/domain/plugin/materialize/workflows.js +31 -0
- package/dist/domain/plugin/materialize/workflows.js.map +1 -0
- package/dist/domain/plugin/members.d.ts +42 -0
- package/dist/domain/plugin/members.d.ts.map +1 -0
- package/dist/domain/plugin/members.js +97 -0
- package/dist/domain/plugin/members.js.map +1 -0
- package/dist/domain/plugin/overlay/documents.d.ts +31 -0
- package/dist/domain/plugin/overlay/documents.d.ts.map +1 -0
- package/dist/domain/plugin/overlay/documents.js +38 -0
- package/dist/domain/plugin/overlay/documents.js.map +1 -0
- package/dist/domain/plugin/overlay/parse.d.ts +16 -0
- package/dist/domain/plugin/overlay/parse.d.ts.map +1 -0
- package/dist/domain/plugin/overlay/parse.js +79 -0
- package/dist/domain/plugin/overlay/parse.js.map +1 -0
- package/dist/domain/plugin/overlay/sanitize.d.ts +10 -0
- package/dist/domain/plugin/overlay/sanitize.d.ts.map +1 -0
- package/dist/domain/plugin/overlay/sanitize.js +103 -0
- package/dist/domain/plugin/overlay/sanitize.js.map +1 -0
- package/dist/domain/plugin/push.d.ts +133 -0
- package/dist/domain/plugin/push.d.ts.map +1 -0
- package/dist/domain/plugin/push.js +800 -0
- package/dist/domain/plugin/push.js.map +1 -0
- package/dist/domain/plugin/search-extractor.d.ts +3 -0
- package/dist/domain/plugin/search-extractor.d.ts.map +1 -0
- package/dist/domain/plugin/search-extractor.js +41 -0
- package/dist/domain/plugin/search-extractor.js.map +1 -0
- package/dist/domain/skill/constants.d.ts +6 -11
- package/dist/domain/skill/constants.d.ts.map +1 -1
- package/dist/domain/skill/constants.js +6 -11
- package/dist/domain/skill/constants.js.map +1 -1
- package/dist/domain/skill/controller.d.ts.map +1 -1
- package/dist/domain/skill/controller.js +33 -30
- package/dist/domain/skill/controller.js.map +1 -1
- package/dist/domain/skill/push.d.ts +9 -10
- package/dist/domain/skill/push.d.ts.map +1 -1
- package/dist/domain/skill/push.js +53 -122
- package/dist/domain/skill/push.js.map +1 -1
- package/dist/domain/skill/search-extractor.d.ts.map +1 -1
- package/dist/domain/skill/search-extractor.js.map +1 -1
- package/dist/domain/skill/storage/artifact-storage.d.ts +26 -29
- package/dist/domain/skill/storage/artifact-storage.d.ts.map +1 -1
- package/dist/domain/skill/storage/artifact-storage.js +6 -103
- package/dist/domain/skill/storage/artifact-storage.js.map +1 -1
- package/dist/domain/skill/storage/zip-gate.d.ts +1 -2
- package/dist/domain/skill/storage/zip-gate.d.ts.map +1 -1
- package/dist/domain/skill/storage/zip-gate.js +56 -126
- package/dist/domain/skill/storage/zip-gate.js.map +1 -1
- package/dist/domain/skill/version-resolution.d.ts +5 -5
- package/dist/domain/skill/version-resolution.d.ts.map +1 -1
- package/dist/domain/skill/version-resolution.js +34 -216
- package/dist/domain/skill/version-resolution.js.map +1 -1
- package/dist/domain/workflow/controller.d.ts.map +1 -1
- package/dist/domain/workflow/controller.js +30 -3
- package/dist/domain/workflow/controller.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -0
- package/dist/domain/workflowexecution/phases.d.ts +21 -0
- package/dist/domain/workflowexecution/phases.d.ts.map +1 -0
- package/dist/domain/workflowexecution/phases.js +31 -0
- package/dist/domain/workflowexecution/phases.js.map +1 -0
- package/dist/extensions/authorizer.d.ts +10 -5
- package/dist/extensions/authorizer.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +4 -1
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +47 -20
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js +20 -24
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/extensions/organization-directory.d.ts +13 -9
- package/dist/extensions/organization-directory.d.ts.map +1 -1
- package/dist/extensions/organization-directory.js.map +1 -1
- package/dist/extensions/resource-authorization.d.ts +33 -0
- package/dist/extensions/resource-authorization.d.ts.map +1 -1
- package/dist/extensions/schedule-fire-caller.d.ts +45 -18
- package/dist/extensions/schedule-fire-caller.d.ts.map +1 -1
- package/dist/extensions/schedule-fire-caller.js +12 -1
- package/dist/extensions/schedule-fire-caller.js.map +1 -1
- package/dist/identity/oidc-verifier.js +8 -1
- package/dist/identity/oidc-verifier.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/apiresource-labels.d.ts +23 -3
- package/dist/pipeline/apiresource-labels.d.ts.map +1 -1
- package/dist/pipeline/apiresource-labels.js +20 -0
- package/dist/pipeline/apiresource-labels.js.map +1 -1
- package/dist/pipeline/apiresource-meta.d.ts +15 -0
- package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
- package/dist/pipeline/apiresource-meta.js +34 -0
- package/dist/pipeline/apiresource-meta.js.map +1 -1
- package/dist/pipeline/errors.d.ts.map +1 -1
- package/dist/pipeline/errors.js.map +1 -1
- package/dist/pipeline/steps/authorization-facts.d.ts +12 -0
- package/dist/pipeline/steps/authorization-facts.d.ts.map +1 -0
- package/dist/pipeline/steps/authorization-facts.js +100 -0
- package/dist/pipeline/steps/authorization-facts.js.map +1 -0
- package/dist/pipeline/steps/delete.d.ts.map +1 -1
- package/dist/pipeline/steps/delete.js +1 -1
- package/dist/pipeline/steps/delete.js.map +1 -1
- package/dist/pipeline/steps/duplicate.d.ts.map +1 -1
- package/dist/pipeline/steps/duplicate.js.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
- package/dist/pipeline/steps/guard-memory-capture.js +5 -3
- package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
- package/dist/pipeline/steps/guard-plugin-managed.d.ts +12 -0
- package/dist/pipeline/steps/guard-plugin-managed.d.ts.map +1 -0
- package/dist/pipeline/steps/guard-plugin-managed.js +96 -0
- package/dist/pipeline/steps/guard-plugin-managed.js.map +1 -0
- package/dist/pipeline/steps/guard-reserved-labels.d.ts +16 -2
- package/dist/pipeline/steps/guard-reserved-labels.d.ts.map +1 -1
- package/dist/pipeline/steps/guard-reserved-labels.js +11 -7
- package/dist/pipeline/steps/guard-reserved-labels.js.map +1 -1
- package/dist/pipeline/steps/helpers.d.ts.map +1 -1
- package/dist/pipeline/steps/helpers.js.map +1 -1
- package/dist/pipeline/steps/index-search.d.ts.map +1 -1
- package/dist/pipeline/steps/index-search.js.map +1 -1
- package/dist/pipeline/steps/load-existing.d.ts.map +1 -1
- package/dist/pipeline/steps/load-existing.js +1 -1
- package/dist/pipeline/steps/load-existing.js.map +1 -1
- package/dist/pipeline/steps/references.d.ts +16 -0
- package/dist/pipeline/steps/references.d.ts.map +1 -1
- package/dist/pipeline/steps/references.js +18 -0
- package/dist/pipeline/steps/references.js.map +1 -1
- package/dist/pipeline/steps/resolve-artifact-source.d.ts +35 -0
- package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -0
- package/dist/pipeline/steps/resolve-artifact-source.js +27 -0
- package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -0
- package/dist/pipeline/steps/server-stamped-reserved-labels.d.ts.map +1 -1
- package/dist/pipeline/steps/server-stamped-reserved-labels.js.map +1 -1
- package/dist/pipeline/steps/slug.d.ts.map +1 -1
- package/dist/pipeline/steps/slug.js.map +1 -1
- package/dist/pipeline/steps/validate-visibility.d.ts +9 -0
- package/dist/pipeline/steps/validate-visibility.d.ts.map +1 -1
- package/dist/pipeline/steps/validate-visibility.js +6 -1
- package/dist/pipeline/steps/validate-visibility.js.map +1 -1
- package/dist/pipeline/steps/validation.d.ts.map +1 -1
- package/dist/pipeline/steps/validation.js.map +1 -1
- package/dist/pipeline/steps/version-archive.d.ts +63 -0
- package/dist/pipeline/steps/version-archive.d.ts.map +1 -0
- package/dist/pipeline/steps/version-archive.js +129 -0
- package/dist/pipeline/steps/version-archive.js.map +1 -0
- package/dist/pipeline/steps/version-history.d.ts +49 -0
- package/dist/pipeline/steps/version-history.d.ts.map +1 -0
- package/dist/pipeline/steps/version-history.js +229 -0
- package/dist/pipeline/steps/version-history.js.map +1 -0
- package/dist/pipeline/steps/visibility-gates.d.ts +8 -0
- package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -1
- package/dist/pipeline/steps/visibility-gates.js +7 -2
- package/dist/pipeline/steps/visibility-gates.js.map +1 -1
- package/dist/query/search/registry.d.ts.map +1 -1
- package/dist/query/search/registry.js +2 -0
- package/dist/query/search/registry.js.map +1 -1
- package/dist/runnerauth/bound-execution.d.ts +27 -0
- package/dist/runnerauth/bound-execution.d.ts.map +1 -0
- package/dist/runnerauth/bound-execution.js +137 -0
- package/dist/runnerauth/bound-execution.js.map +1 -0
- package/dist/runnerauth/built-in-runner-credential-provider.d.ts +28 -0
- package/dist/runnerauth/built-in-runner-credential-provider.d.ts.map +1 -0
- package/dist/runnerauth/built-in-runner-credential-provider.js +217 -0
- package/dist/runnerauth/built-in-runner-credential-provider.js.map +1 -0
- package/dist/runnerauth/constants.d.ts +63 -0
- package/dist/runnerauth/constants.d.ts.map +1 -0
- package/dist/runnerauth/constants.js +63 -0
- package/dist/runnerauth/constants.js.map +1 -0
- package/dist/runnerauth/dispatch-credential.d.ts +38 -0
- package/dist/runnerauth/dispatch-credential.d.ts.map +1 -0
- package/dist/runnerauth/dispatch-credential.js +17 -0
- package/dist/runnerauth/dispatch-credential.js.map +1 -0
- package/dist/runnerauth/runner-credential-provider.d.ts +49 -11
- package/dist/runnerauth/runner-credential-provider.d.ts.map +1 -1
- package/dist/runnerauth/runner-credential-provider.js +16 -4
- package/dist/runnerauth/runner-credential-provider.js.map +1 -1
- package/dist/runnerauth/runner-subject-verifier.d.ts +14 -0
- package/dist/runnerauth/runner-subject-verifier.d.ts.map +1 -0
- package/dist/runnerauth/runner-subject-verifier.js +115 -0
- package/dist/runnerauth/runner-subject-verifier.js.map +1 -0
- package/dist/runnerauth/runnerauth.d.ts +33 -4
- package/dist/runnerauth/runnerauth.d.ts.map +1 -1
- package/dist/runnerauth/runnerauth.js +131 -35
- package/dist/runnerauth/runnerauth.js.map +1 -1
- package/dist/temporal/agentexecution/engine-client.d.ts +13 -0
- package/dist/temporal/agentexecution/engine-client.d.ts.map +1 -1
- package/dist/temporal/agentexecution/engine-client.js +10 -2
- package/dist/temporal/agentexecution/engine-client.js.map +1 -1
- package/dist/temporal/agentexecution/workflow-input.d.ts +13 -0
- package/dist/temporal/agentexecution/workflow-input.d.ts.map +1 -1
- package/dist/temporal/agentexecution/workflows/invoke-agent-execution.d.ts.map +1 -1
- package/dist/temporal/agentexecution/workflows/invoke-agent-execution.js +35 -31
- package/dist/temporal/agentexecution/workflows/invoke-agent-execution.js.map +1 -1
- package/dist/temporal/schedule/run-starter.d.ts +1 -1
- package/dist/temporal/schedule/run-starter.d.ts.map +1 -1
- package/dist/temporal/schedule/run-starter.js +14 -1
- package/dist/temporal/schedule/run-starter.js.map +1 -1
- package/dist/temporal/workflowexecution/engine-client.d.ts +24 -0
- package/dist/temporal/workflowexecution/engine-client.d.ts.map +1 -1
- package/dist/temporal/workflowexecution/engine-client.js +26 -19
- package/dist/temporal/workflowexecution/engine-client.js.map +1 -1
- package/dist/temporal/workflowexecution/workflow-input.d.ts +14 -0
- package/dist/temporal/workflowexecution/workflow-input.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/archive/__tests__/archive.test.ts +233 -0
- package/src/{domain/skill → archive}/__tests__/prefilter.test.ts +1 -1
- package/src/archive/content-store.ts +132 -0
- package/src/archive/inflate.ts +107 -0
- package/src/archive/limits.ts +42 -0
- package/src/archive/open.ts +131 -0
- package/src/{domain/skill/storage → archive}/prefilter.ts +5 -0
- package/src/archive/write.ts +54 -0
- package/src/authorization/README.md +124 -0
- package/src/authorization/__tests__/authorizer.test.ts +719 -0
- package/src/authorization/__tests__/derived-tuples.test.ts +802 -0
- package/src/authorization/__tests__/drivers.ts +70 -0
- package/src/authorization/__tests__/evaluator.test.ts +359 -0
- package/src/authorization/__tests__/facts.test.ts +155 -0
- package/src/authorization/__tests__/fixtures/fga/agent-channel-owner.fga.yaml +112 -0
- package/src/authorization/__tests__/fixtures/fga/agent-share-owner.fga.yaml +109 -0
- package/src/authorization/__tests__/fixtures/fga/artifact-org-and-owner.fga.yaml +128 -0
- package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +410 -0
- package/src/authorization/__tests__/fixtures/fga/channel-app-owner.fga.yaml +125 -0
- package/src/authorization/__tests__/fixtures/fga/channel-participation.fga.yaml +201 -0
- package/src/authorization/__tests__/fixtures/fga/channel-session-visibility.fga.yaml +187 -0
- package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
- package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +271 -0
- package/src/authorization/__tests__/fixtures/fga/memory-subject-only.fga.yaml +72 -0
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +328 -0
- package/src/authorization/__tests__/fixtures/fga/org-shared-environment.fga.yaml +144 -0
- package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +223 -0
- package/src/authorization/__tests__/fixtures/fga/provider-standing-viewer.fga.yaml +40 -0
- package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
- package/src/authorization/__tests__/fixtures/fga/reserved-label-writer.fga.yaml +41 -0
- package/src/authorization/__tests__/fixtures/fga/schedule-owner.fga.yaml +113 -0
- package/src/authorization/__tests__/fixtures/fga/schedule-session-visibility.fga.yaml +214 -0
- package/src/authorization/__tests__/fixtures/fga/session-personal-resource.fga.yaml +117 -0
- package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +192 -0
- package/src/authorization/__tests__/lane-admission.test.ts +115 -0
- package/src/authorization/__tests__/list-read-scope.measure.test.ts +317 -0
- package/src/authorization/__tests__/list-read-scope.test.ts +796 -0
- package/src/authorization/__tests__/organization-directory.test.ts +236 -0
- package/src/authorization/__tests__/person.test.ts +114 -0
- package/src/authorization/__tests__/posture.test.ts +25 -0
- package/src/authorization/__tests__/schedule-fire-caller.test.ts +134 -0
- package/src/authorization/__tests__/store-tests.test.ts +306 -0
- package/src/authorization/__tests__/support.ts +101 -0
- package/src/authorization/__tests__/tuples.test.ts +62 -0
- package/src/authorization/__tests__/wire-permissions.test.ts +154 -0
- package/src/authorization/authorizer.ts +208 -0
- package/src/authorization/derived-tuples.ts +384 -0
- package/src/authorization/evaluator.ts +283 -0
- package/src/authorization/facts.ts +47 -0
- package/src/authorization/lane-admission.ts +73 -0
- package/src/authorization/list-read-scope.ts +216 -0
- package/src/authorization/model/__tests__/registry.test.ts +317 -0
- package/src/authorization/model/agent.ts +64 -0
- package/src/authorization/model/agent_channel.ts +49 -0
- package/src/authorization/model/agent_execution.ts +33 -0
- package/src/authorization/model/agent_instance.ts +66 -0
- package/src/authorization/model/agent_share.ts +40 -0
- package/src/authorization/model/api_key.ts +28 -0
- package/src/authorization/model/artifact.ts +38 -0
- package/src/authorization/model/channel_app.ts +39 -0
- package/src/authorization/model/default-of.ts +99 -0
- package/src/authorization/model/environment.ts +48 -0
- package/src/authorization/model/execution_context.ts +20 -0
- package/src/authorization/model/iam_policy.ts +42 -0
- package/src/authorization/model/identity_account.ts +26 -0
- package/src/authorization/model/index.ts +108 -0
- package/src/authorization/model/mcp_server.ts +59 -0
- package/src/authorization/model/memory.ts +27 -0
- package/src/authorization/model/oauth_app.ts +42 -0
- package/src/authorization/model/organization.ts +55 -0
- package/src/authorization/model/plugin.ts +66 -0
- package/src/authorization/model/project.ts +47 -0
- package/src/authorization/model/rewrite.ts +213 -0
- package/src/authorization/model/schedule.ts +40 -0
- package/src/authorization/model/session.ts +50 -0
- package/src/authorization/model/skill.ts +60 -0
- package/src/authorization/model/workflow.ts +60 -0
- package/src/authorization/model/workflow_execution.ts +44 -0
- package/src/authorization/model/workflow_instance.ts +122 -0
- package/src/authorization/organization-directory.ts +114 -0
- package/src/authorization/person.ts +68 -0
- package/src/authorization/posture.ts +49 -0
- package/src/authorization/schedule-fire-caller.ts +87 -0
- package/src/authorization/store-test-kit.ts +454 -0
- package/src/authorization/tuples.ts +190 -0
- package/src/boot/compose.ts +246 -52
- package/src/boot/inprocess.ts +115 -31
- package/src/domain/agent/controller.ts +11 -0
- package/src/domain/executioncontext/__tests__/executioncontext.test.ts +104 -0
- package/src/domain/executioncontext/__tests__/resolve-values-capability.test.ts +33 -4
- package/src/domain/executioncontext/resolve-values-for-caller.ts +79 -22
- package/src/domain/iampolicy/__tests__/membership.test.ts +357 -3
- package/src/domain/iampolicy/constants.ts +12 -0
- package/src/domain/iampolicy/membership.ts +221 -66
- package/src/domain/identityaccount/__tests__/account-for-stamp.test.ts +111 -0
- package/src/domain/identityaccount/actor.ts +84 -0
- package/src/domain/identityaccount/resolve.ts +31 -0
- package/src/domain/mcpserver/__tests__/connect.test.ts +17 -2
- package/src/domain/mcpserver/connect-execution-id.ts +34 -0
- package/src/domain/mcpserver/connect.ts +38 -3
- package/src/domain/mcpserver/controller.ts +11 -0
- package/src/domain/mcpserver/engine.ts +9 -3
- package/src/domain/mcpserver/start-connect.ts +1 -1
- package/src/domain/platform/controller.ts +24 -11
- package/src/domain/plugin/__tests__/materialize.test.ts +303 -0
- package/src/domain/plugin/__tests__/overlay-parse.test.ts +85 -0
- package/src/domain/plugin/__tests__/plugin.test.ts +796 -0
- package/src/domain/plugin/__tests__/sanitize.test.ts +174 -0
- package/src/domain/plugin/archive.ts +89 -0
- package/src/domain/plugin/constants.ts +53 -0
- package/src/domain/plugin/controller.ts +913 -0
- package/src/domain/plugin/materialize/agent.ts +186 -0
- package/src/domain/plugin/materialize/default-agent-instructions.ts +59 -0
- package/src/domain/plugin/materialize/identity.ts +67 -0
- package/src/domain/plugin/materialize/mcp-servers.ts +175 -0
- package/src/domain/plugin/materialize/plan.ts +124 -0
- package/src/domain/plugin/materialize/ports.ts +53 -0
- package/src/domain/plugin/materialize/skills.ts +68 -0
- package/src/domain/plugin/materialize/workflows.ts +51 -0
- package/src/domain/plugin/members.ts +180 -0
- package/src/domain/plugin/overlay/documents.ts +78 -0
- package/src/domain/plugin/overlay/parse.ts +115 -0
- package/src/domain/plugin/overlay/sanitize.ts +151 -0
- package/src/domain/plugin/push.ts +1062 -0
- package/src/domain/plugin/search-extractor.ts +60 -0
- package/src/domain/skill/constants.ts +11 -14
- package/src/domain/skill/controller.ts +44 -36
- package/src/domain/skill/push.ts +61 -156
- package/src/domain/skill/search-extractor.ts +3 -1
- package/src/domain/skill/storage/artifact-storage.ts +23 -124
- package/src/domain/skill/storage/zip-gate.ts +58 -154
- package/src/domain/skill/version-resolution.ts +67 -269
- package/src/domain/workflow/controller.ts +38 -4
- package/src/domain/workflow/registry/data/task-kind-registry.json +1 -0
- package/src/domain/workflowexecution/__tests__/phases.test.ts +58 -0
- package/src/domain/workflowexecution/phases.ts +33 -0
- package/src/extensions/__tests__/built-in-authorization-composed.test.ts +835 -0
- package/src/extensions/__tests__/composed-support.ts +32 -1
- package/src/extensions/__tests__/extension-composition.test.ts +42 -1
- package/src/extensions/__tests__/list-read-scope.test.ts +137 -33
- package/src/extensions/__tests__/role-reconciliation-composed.test.ts +209 -0
- package/src/extensions/__tests__/tier-truthfulness.test.ts +6 -14
- package/src/extensions/authorizer.ts +10 -5
- package/src/extensions/drivers.ts +4 -1
- package/src/extensions/list-read-scope.ts +67 -45
- package/src/extensions/organization-directory.ts +13 -9
- package/src/extensions/resource-authorization.ts +34 -0
- package/src/extensions/schedule-fire-caller.ts +49 -18
- package/src/identity/__tests__/oidc-verifier.test.ts +22 -0
- package/src/identity/oidc-verifier.ts +8 -1
- package/src/index.ts +51 -1
- package/src/pipeline/__tests__/kind-by-id-prefix.test.ts +75 -0
- package/src/pipeline/__tests__/router-transport.test.ts +1 -3
- package/src/pipeline/apiresource-labels.ts +31 -3
- package/src/pipeline/apiresource-meta.ts +41 -0
- package/src/pipeline/errors.ts +5 -5
- package/src/pipeline/steps/__tests__/authorize-annotation-completeness.test.ts +1 -20
- package/src/pipeline/steps/__tests__/guard-memory-capture.test.ts +58 -44
- package/src/pipeline/steps/__tests__/guard-plugin-managed.test.ts +151 -0
- package/src/pipeline/steps/__tests__/guard-reserved-labels.test.ts +83 -8
- package/src/pipeline/steps/authorization-facts.ts +131 -0
- package/src/pipeline/steps/delete.ts +11 -3
- package/src/pipeline/steps/duplicate.ts +8 -2
- package/src/pipeline/steps/guard-memory-capture.ts +5 -3
- package/src/pipeline/steps/guard-plugin-managed.ts +133 -0
- package/src/pipeline/steps/guard-reserved-labels.ts +29 -8
- package/src/pipeline/steps/helpers.ts +4 -1
- package/src/pipeline/steps/index-search.ts +28 -15
- package/src/pipeline/steps/load-existing.ts +12 -3
- package/src/pipeline/steps/references.ts +36 -2
- package/src/pipeline/steps/resolve-artifact-source.ts +66 -0
- package/src/pipeline/steps/server-stamped-reserved-labels.ts +2 -1
- package/src/pipeline/steps/slug.ts +7 -2
- package/src/pipeline/steps/validate-visibility.ts +9 -2
- package/src/pipeline/steps/validation.ts +3 -1
- package/src/pipeline/steps/version-archive.ts +225 -0
- package/src/pipeline/steps/version-history.ts +362 -0
- package/src/pipeline/steps/visibility-gates.ts +12 -9
- package/src/query/README.md +1 -1
- package/src/query/search/__tests__/criteria.test.ts +6 -7
- package/src/query/search/__tests__/query-store.test.ts +9 -2
- package/src/query/search/__tests__/registry.test.ts +6 -4
- package/src/query/search/registry.ts +6 -1
- package/src/runnerauth/__tests__/bound-execution.test.ts +334 -0
- package/src/runnerauth/__tests__/built-in-runner-credential-provider.test.ts +516 -0
- package/src/runnerauth/__tests__/dispatch-credential.test.ts +94 -0
- package/src/runnerauth/__tests__/runner-credential-provider.test.ts +27 -0
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +497 -0
- package/src/runnerauth/__tests__/runner-subject-verifier.test.ts +541 -0
- package/src/runnerauth/bound-execution.ts +270 -0
- package/src/runnerauth/built-in-runner-credential-provider.ts +300 -0
- package/src/runnerauth/constants.ts +74 -0
- package/src/runnerauth/dispatch-credential.ts +63 -0
- package/src/runnerauth/runner-credential-provider.ts +60 -11
- package/src/runnerauth/runner-subject-verifier.ts +152 -0
- package/src/runnerauth/runnerauth.ts +148 -38
- package/src/temporal/agentexecution/__tests__/engine-client.test.ts +107 -38
- package/src/temporal/agentexecution/__tests__/invoke-workflow.test.ts +105 -2
- package/src/temporal/agentexecution/engine-client.ts +27 -2
- package/src/temporal/agentexecution/workflow-input.ts +13 -0
- package/src/temporal/agentexecution/workflows/invoke-agent-execution.ts +90 -44
- package/src/temporal/schedule/__tests__/run-starter.test.ts +86 -24
- package/src/temporal/schedule/run-starter.ts +31 -8
- package/src/temporal/workflowexecution/__tests__/engine-client.test.ts +139 -33
- package/src/temporal/workflowexecution/engine-client.ts +48 -21
- package/src/temporal/workflowexecution/workflow-input.ts +14 -0
- package/dist/domain/skill/storage/prefilter.d.ts.map +0 -1
- package/dist/domain/skill/storage/prefilter.js.map +0 -1
- /package/dist/{domain/skill/storage → archive}/prefilter.js +0 -0
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* no unit registered an Authorizer); a composition with its own
|
|
8
8
|
* Authorizer has its own onboarding and never constructs this.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Three moments, one set of arms (`roleFor`, the pure function the first
|
|
11
|
+
* and third share):
|
|
11
12
|
*
|
|
12
13
|
* onAccountCreated(account, caller) — a person's FIRST provisioning, and
|
|
13
14
|
* only that (the identity-account domain's AccountCreatedHook, run by
|
|
@@ -50,6 +51,30 @@
|
|
|
50
51
|
* email and name — so its audit actor reads like every other write on
|
|
51
52
|
* that laptop.
|
|
52
53
|
*
|
|
54
|
+
* ensureRolesForExistingAccounts() — the built-in posture's boot
|
|
55
|
+
* reconciliation, ONCE per database. The first moment runs only on the
|
|
56
|
+
* call that CREATES an account, so a self-host whose people were
|
|
57
|
+
* provisioned before the rules existed (3.15.x with OIDC on) holds
|
|
58
|
+
* accounts with no role rows, and under an enforcing authorizer every
|
|
59
|
+
* one of them would be an outsider on every organization with nobody
|
|
60
|
+
* able to grant a way back. At the first boot where the bootstrap-state
|
|
61
|
+
* marker (ROLES_RECONCILED_KEY) is absent, the arms above run for every
|
|
62
|
+
* PERSON account (`isPersonAccount`: not a machine account, the row-
|
|
63
|
+
* level twin of the `user`-class gate), acting as that account, in
|
|
64
|
+
* creation order — the order the sign-ins would have run the hook in,
|
|
65
|
+
* so arm 4 hands an unclaimed organization to its first sign-in and
|
|
66
|
+
* not to whoever sorts first by id — and the marker is written after
|
|
67
|
+
* the last account. A fault propagates and the boot fails loudly (the
|
|
68
|
+
* storage stage's posture) with the marker unset; the grant path is
|
|
69
|
+
* idempotent and an organization already held is skipped, so the next
|
|
70
|
+
* boot converges. The marker, not "zero rows", is what makes it
|
|
71
|
+
* one-shot: a database whose every role was revoked after the marker is
|
|
72
|
+
* never handed back to anyone by a reboot (plan finding 2's reason,
|
|
73
|
+
* applied to the whole store). Accounts are read through the generic
|
|
74
|
+
* Store as the organizations and blueprints are (Q-S4-5) — the account
|
|
75
|
+
* port carries no enumeration, by its own rule that a port does not
|
|
76
|
+
* carry a method only one edition calls, and this act is open source's.
|
|
77
|
+
*
|
|
53
78
|
* What a creator stamp is. The rules read `status.audit.spec_audit
|
|
54
79
|
* .created_by.id` off organizations and blueprints. That stamp is the
|
|
55
80
|
* caller's identityId at the time: a provisioned caller's ACCOUNT id, an
|
|
@@ -92,6 +117,8 @@ import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb"
|
|
|
92
117
|
import { WorkflowSchema } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/api_pb";
|
|
93
118
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
94
119
|
import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
120
|
+
import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
121
|
+
import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
|
|
95
122
|
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
96
123
|
import { OrganizationSchema } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
97
124
|
|
|
@@ -101,8 +128,10 @@ import { SYSTEM_OPERATOR_IDENTITY_ID } from "../../pipeline/interceptors/auth.js
|
|
|
101
128
|
import { auditOf } from "../../pipeline/steps/defaults.js";
|
|
102
129
|
import { metadataOf } from "../../pipeline/steps/shapes.js";
|
|
103
130
|
import type { Store } from "../../store/interface.js";
|
|
131
|
+
import { rfc3339Seconds } from "../../store/rfc3339.js";
|
|
132
|
+
import { accountAsCaller } from "../identityaccount/actor.js";
|
|
104
133
|
import type { AccountCreatedHook } from "../identityaccount/provisioning.js";
|
|
105
|
-
import { BLUEPRINT_KINDS } from "./constants.js";
|
|
134
|
+
import { BLUEPRINT_KINDS, ROLES_RECONCILED_KEY } from "./constants.js";
|
|
106
135
|
import type { IamPolicyGrantPath } from "./grant-path.js";
|
|
107
136
|
import { organizationRole, relationOf } from "./specs.js";
|
|
108
137
|
import type { IamPolicyStore } from "./store.js";
|
|
@@ -119,6 +148,8 @@ export interface MembershipRulesDeps {
|
|
|
119
148
|
export interface MembershipRules extends AccountCreatedHook {
|
|
120
149
|
/** The trusted-local boot ensure: `owner` wherever no owner row exists. */
|
|
121
150
|
ensureOperatorOwnership(operator: IdentityAccount): Promise<void>;
|
|
151
|
+
/** The built-in posture's boot reconciliation: the arms for every person provisioned before the rules existed, once per database. */
|
|
152
|
+
ensureRolesForExistingAccounts(): Promise<void>;
|
|
122
153
|
}
|
|
123
154
|
|
|
124
155
|
/**
|
|
@@ -142,17 +173,106 @@ const ORGANIZATION = kindEnumName(ApiResourceKind.organization);
|
|
|
142
173
|
const IDENTITY_ACCOUNT = kindEnumName(ApiResourceKind.identity_account);
|
|
143
174
|
|
|
144
175
|
/** What the scan keeps of a resource: its id, its organization (blueprints), its creator stamp. */
|
|
145
|
-
interface ScannedResource {
|
|
176
|
+
export interface ScannedResource {
|
|
146
177
|
readonly id: string;
|
|
147
178
|
readonly org: string;
|
|
148
179
|
readonly createdBy: string;
|
|
149
180
|
}
|
|
150
181
|
|
|
151
|
-
/**
|
|
152
|
-
|
|
182
|
+
/**
|
|
183
|
+
* A creator stamp that names a person: non-empty and not the unconfigured
|
|
184
|
+
* laptop's placeholder. Exported for the built-in authorizer's derivation
|
|
185
|
+
* (authorization/derived-tuples.ts), which turns a stamp into an owner or
|
|
186
|
+
* creator tuple only when this says the stamp is somebody's — the one
|
|
187
|
+
* predicate, read from the module that owns the doctrine above.
|
|
188
|
+
*/
|
|
189
|
+
export function isPersonStamp(stamp: string): boolean {
|
|
153
190
|
return stamp !== "" && stamp !== SYSTEM_OPERATOR_IDENTITY_ID;
|
|
154
191
|
}
|
|
155
192
|
|
|
193
|
+
/**
|
|
194
|
+
* An account row that is a person's — the row-level twin of the hook's
|
|
195
|
+
* `user`-class gate, for the reconciliation, which has a row and no
|
|
196
|
+
* caller. A machine account (`is_machine_account`, or the `machine`
|
|
197
|
+
* provisioning mode) earns no role, exactly as a `machine`-class caller
|
|
198
|
+
* earns none at the hook.
|
|
199
|
+
*/
|
|
200
|
+
export function isPersonAccount(account: IdentityAccount): boolean {
|
|
201
|
+
const spec = account.spec;
|
|
202
|
+
return (
|
|
203
|
+
spec !== undefined &&
|
|
204
|
+
!spec.isMachineAccount &&
|
|
205
|
+
spec.provisioningMode !== IdentityAccountProvisioningMode.machine
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** One organization's question for one account: everything the five arms read, resolved by the caller. */
|
|
210
|
+
export interface RoleQuestion {
|
|
211
|
+
readonly accountId: string;
|
|
212
|
+
/** The account's issuer subject (`spec.idp_id`); a stamp equal to it is the account's own (the alias rule). */
|
|
213
|
+
readonly subject: string;
|
|
214
|
+
readonly email: string;
|
|
215
|
+
/** STIGMER_OPERATOR_EMAIL as configured; "" matches nobody. */
|
|
216
|
+
readonly operatorEmail: string;
|
|
217
|
+
readonly organization: ScannedResource;
|
|
218
|
+
readonly blueprintsInOrganization: ReadonlyArray<ScannedResource>;
|
|
219
|
+
/** Whether ANY role row exists on the organization — arm 4's "zero rows", read by the caller through the port. */
|
|
220
|
+
readonly organizationHasRows: boolean;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The five arms in their ruled order, as one pure function over what they
|
|
225
|
+
* read — the one statement of "which role does this person get here",
|
|
226
|
+
* shared by the first-sign-in hook and the boot reconciliation so the two
|
|
227
|
+
* moments cannot drift. Arms 3 and 4 both answer `admin`; 3 comes first
|
|
228
|
+
* because it is a string compare and 4 needs the rows read.
|
|
229
|
+
*/
|
|
230
|
+
export function roleFor(question: RoleQuestion): IamRole {
|
|
231
|
+
const {
|
|
232
|
+
accountId,
|
|
233
|
+
subject,
|
|
234
|
+
email,
|
|
235
|
+
operatorEmail,
|
|
236
|
+
organization,
|
|
237
|
+
blueprintsInOrganization,
|
|
238
|
+
organizationHasRows,
|
|
239
|
+
} = question;
|
|
240
|
+
const isMine = (stamp: string): boolean =>
|
|
241
|
+
stamp !== "" && (stamp === subject || stamp === accountId);
|
|
242
|
+
if (isMine(organization.createdBy)) {
|
|
243
|
+
return IamRole.owner;
|
|
244
|
+
}
|
|
245
|
+
if (blueprintsInOrganization.some((b) => isMine(b.createdBy))) {
|
|
246
|
+
return IamRole.admin;
|
|
247
|
+
}
|
|
248
|
+
if (operatorEmail !== "" && email === operatorEmail) {
|
|
249
|
+
return IamRole.admin;
|
|
250
|
+
}
|
|
251
|
+
const anotherPersonStamped = [
|
|
252
|
+
organization.createdBy,
|
|
253
|
+
...blueprintsInOrganization.map((b) => b.createdBy),
|
|
254
|
+
].some((stamp) => isPersonStamp(stamp) && !isMine(stamp));
|
|
255
|
+
if (!anotherPersonStamped && !organizationHasRows) {
|
|
256
|
+
return IamRole.admin;
|
|
257
|
+
}
|
|
258
|
+
return IamRole.member;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** The world one pass of the arms reads: scanned ONCE by the caller, whether for one account or for all. */
|
|
262
|
+
interface ScannedWorld {
|
|
263
|
+
readonly organizations: ReadonlyArray<ScannedResource>;
|
|
264
|
+
readonly blueprints: ReadonlyArray<ScannedResource>;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** `spec_audit.created_at` in epoch milliseconds; a row with no stamp sorts first (it is the oldest thing we know nothing about). */
|
|
268
|
+
function createdAtMillisOf(account: IdentityAccount): number {
|
|
269
|
+
const stamp = account.status?.audit?.specAudit?.createdAt;
|
|
270
|
+
if (stamp === undefined) {
|
|
271
|
+
return Number.NEGATIVE_INFINITY;
|
|
272
|
+
}
|
|
273
|
+
return Number(stamp.seconds) * 1000 + Math.floor(stamp.nanos / 1_000_000);
|
|
274
|
+
}
|
|
275
|
+
|
|
156
276
|
export function newMembershipRules(deps: MembershipRulesDeps): MembershipRules {
|
|
157
277
|
const { grantPath, policies, store, operatorEmail } = deps;
|
|
158
278
|
|
|
@@ -195,13 +315,79 @@ export function newMembershipRules(deps: MembershipRulesDeps): MembershipRules {
|
|
|
195
315
|
);
|
|
196
316
|
}
|
|
197
317
|
|
|
318
|
+
/** The whole world one pass reads, scanned once: every organization and every blueprint. */
|
|
319
|
+
async function scanWorld(): Promise<ScannedWorld> {
|
|
320
|
+
return {
|
|
321
|
+
organizations: await scan(ApiResourceKind.organization),
|
|
322
|
+
blueprints: await scanBlueprints(),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* The arms for ONE account over a scanned world: a row on every
|
|
328
|
+
* organization the account holds none on, granted as `caller`. Shared
|
|
329
|
+
* by the hook (one account, the world scanned for it) and the
|
|
330
|
+
* reconciliation (the world scanned once for every account).
|
|
331
|
+
*/
|
|
332
|
+
async function applyRulesTo(
|
|
333
|
+
account: IdentityAccount,
|
|
334
|
+
caller: CallerIdentity,
|
|
335
|
+
world: ScannedWorld,
|
|
336
|
+
): Promise<void> {
|
|
337
|
+
const accountId = account.metadata?.id ?? "";
|
|
338
|
+
if (accountId === "") {
|
|
339
|
+
throw new Error("membership rules: the account carries no id");
|
|
340
|
+
}
|
|
341
|
+
const subject = account.spec?.idpId ?? "";
|
|
342
|
+
const email = account.spec?.email ?? "";
|
|
343
|
+
const held = await organizationsHeldBy(accountId);
|
|
344
|
+
|
|
345
|
+
for (const organization of world.organizations) {
|
|
346
|
+
if (held.has(organization.id)) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const blueprintsInOrganization = world.blueprints.filter(
|
|
350
|
+
(blueprint) => blueprint.org === organization.id,
|
|
351
|
+
);
|
|
352
|
+
const role = roleFor({
|
|
353
|
+
accountId,
|
|
354
|
+
subject,
|
|
355
|
+
email,
|
|
356
|
+
operatorEmail,
|
|
357
|
+
organization,
|
|
358
|
+
blueprintsInOrganization,
|
|
359
|
+
organizationHasRows:
|
|
360
|
+
(await policies.findByResource(ORGANIZATION, organization.id))
|
|
361
|
+
.length > 0,
|
|
362
|
+
});
|
|
363
|
+
await grantPath.grant(
|
|
364
|
+
organizationRole(accountId, role, organization.id),
|
|
365
|
+
caller,
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Every person account the store holds, oldest first (creation stamp, then id) — the order their sign-ins ran in. */
|
|
371
|
+
async function scanPersonAccounts(): Promise<IdentityAccount[]> {
|
|
372
|
+
const rows = await store.listResources(ApiResourceKind.identity_account);
|
|
373
|
+
return rows
|
|
374
|
+
.map((bytes) => fromBinary(IdentityAccountSchema, bytes))
|
|
375
|
+
.filter(isPersonAccount)
|
|
376
|
+
.sort((a, b) => {
|
|
377
|
+
const byCreation = createdAtMillisOf(a) - createdAtMillisOf(b);
|
|
378
|
+
if (byCreation !== 0) {
|
|
379
|
+
return byCreation;
|
|
380
|
+
}
|
|
381
|
+
return (a.metadata?.id ?? "").localeCompare(b.metadata?.id ?? "");
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
198
385
|
return {
|
|
199
386
|
async onAccountCreated(account, caller): Promise<void> {
|
|
200
387
|
if (caller.callerClass !== "user") {
|
|
201
388
|
return;
|
|
202
389
|
}
|
|
203
|
-
|
|
204
|
-
if (accountId === "") {
|
|
390
|
+
if ((account.metadata?.id ?? "") === "") {
|
|
205
391
|
throw new Error(
|
|
206
392
|
"membership rules: the provisioned account carries no id",
|
|
207
393
|
);
|
|
@@ -210,44 +396,33 @@ export function newMembershipRules(deps: MembershipRulesDeps): MembershipRules {
|
|
|
210
396
|
if (organizations.length === 0) {
|
|
211
397
|
return;
|
|
212
398
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const blueprints = await scanBlueprints();
|
|
399
|
+
await applyRulesTo(account, caller, {
|
|
400
|
+
organizations,
|
|
401
|
+
blueprints: await scanBlueprints(),
|
|
402
|
+
});
|
|
403
|
+
},
|
|
219
404
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
} else if (operatorEmail !== "" && email === operatorEmail) {
|
|
233
|
-
role = IamRole.admin;
|
|
234
|
-
} else if (
|
|
235
|
-
![
|
|
236
|
-
organization.createdBy,
|
|
237
|
-
...inOrganization.map((b) => b.createdBy),
|
|
238
|
-
].some((stamp) => isPersonStamp(stamp) && !isMine(stamp)) &&
|
|
239
|
-
(await policies.findByResource(ORGANIZATION, organization.id))
|
|
240
|
-
.length === 0
|
|
241
|
-
) {
|
|
242
|
-
role = IamRole.admin;
|
|
243
|
-
} else {
|
|
244
|
-
role = IamRole.member;
|
|
405
|
+
async ensureRolesForExistingAccounts(): Promise<void> {
|
|
406
|
+
if ((await store.bootstrapState.get(ROLES_RECONCILED_KEY)) !== "") {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const accounts = await scanPersonAccounts();
|
|
410
|
+
if (accounts.length > 0) {
|
|
411
|
+
const world = await scanWorld();
|
|
412
|
+
for (const account of accounts) {
|
|
413
|
+
// As the account itself (actor.ts, the one construction), so the
|
|
414
|
+
// row's audit actor reads exactly as the person's own first
|
|
415
|
+
// sign-in would have stamped it.
|
|
416
|
+
await applyRulesTo(account, accountAsCaller(account), world);
|
|
245
417
|
}
|
|
246
|
-
await grantPath.grant(
|
|
247
|
-
organizationRole(accountId, role, organization.id),
|
|
248
|
-
caller,
|
|
249
|
-
);
|
|
250
418
|
}
|
|
419
|
+
// After the last account, never before: a fault above leaves the
|
|
420
|
+
// marker unset and the next boot converges (the grant path is
|
|
421
|
+
// idempotent; an organization already held is skipped).
|
|
422
|
+
await store.bootstrapState.set(
|
|
423
|
+
ROLES_RECONCILED_KEY,
|
|
424
|
+
rfc3339Seconds(new Date()),
|
|
425
|
+
);
|
|
251
426
|
},
|
|
252
427
|
|
|
253
428
|
async ensureOperatorOwnership(operator): Promise<void> {
|
|
@@ -255,7 +430,10 @@ export function newMembershipRules(deps: MembershipRulesDeps): MembershipRules {
|
|
|
255
430
|
if (accountId === "") {
|
|
256
431
|
throw new Error("membership rules: the operator account carries no id");
|
|
257
432
|
}
|
|
258
|
-
|
|
433
|
+
// The operator acting as its account (domain/identityaccount/actor.ts,
|
|
434
|
+
// the one construction): the row's audit actor is the account,
|
|
435
|
+
// named the way every other trusted-local write names it.
|
|
436
|
+
const actor = accountAsCaller(operator);
|
|
259
437
|
for (const organization of await scan(ApiResourceKind.organization)) {
|
|
260
438
|
const owners = await policies.findByResourceWithRelations(
|
|
261
439
|
ORGANIZATION,
|
|
@@ -273,26 +451,3 @@ export function newMembershipRules(deps: MembershipRulesDeps): MembershipRules {
|
|
|
273
451
|
},
|
|
274
452
|
};
|
|
275
453
|
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* The operator acting as its account: the trusted-local identity shape
|
|
279
|
-
* (pipeline/interceptors/auth.ts trustedLocalIdentityFor — no issuer, no
|
|
280
|
-
* token; email and display name only when known) with the account id as
|
|
281
|
-
* the principal, so the row's audit actor is the account, named the way
|
|
282
|
-
* every other trusted-local write names it.
|
|
283
|
-
*/
|
|
284
|
-
function operatorActor(
|
|
285
|
-
operator: IdentityAccount,
|
|
286
|
-
accountId: string,
|
|
287
|
-
): CallerIdentity {
|
|
288
|
-
const email = operator.spec?.email ?? "";
|
|
289
|
-
const displayName = operator.metadata?.name ?? "";
|
|
290
|
-
return {
|
|
291
|
-
identityId: accountId,
|
|
292
|
-
callerClass: "user",
|
|
293
|
-
issuer: "",
|
|
294
|
-
rawToken: "",
|
|
295
|
-
...(email !== "" ? { email } : {}),
|
|
296
|
-
...(displayName !== "" ? { displayName } : {}),
|
|
297
|
-
};
|
|
298
|
-
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins `accountForStamp` (resolve.ts): the account a row's CREATOR STAMP
|
|
3
|
+
* names, read the two ways a stamp has been written — as an account id
|
|
4
|
+
* (rows stamped since 3.15.0) and as the raw issuer subject (rows the
|
|
5
|
+
* 3.14.x verifiers stamped) — stated ONCE so the schedule fire caller and
|
|
6
|
+
* the runner-subject verifier, which both make a server lane act as the
|
|
7
|
+
* person a row names, cannot resolve the same stamp two ways. The read
|
|
8
|
+
* order is `accountForCaller`'s: by id first, then the direct subject
|
|
9
|
+
* lookup.
|
|
10
|
+
*
|
|
11
|
+
* - an account-id stamp resolves by that id;
|
|
12
|
+
* - a raw-subject stamp resolves through the direct lookup;
|
|
13
|
+
* - the empty stamp is `undefined` with NO read — the store is never
|
|
14
|
+
* asked about "";
|
|
15
|
+
* - a stamp naming nobody (the laptop's `"system"`, a trusted-local
|
|
16
|
+
* email, a deleted account) is `undefined` — the CALLER decides what
|
|
17
|
+
* that means (the fire caller's deterministic refusal; the verifier's
|
|
18
|
+
* liveness sentence); this function never throws for it;
|
|
19
|
+
* - a store fault propagates as the same error object.
|
|
20
|
+
*
|
|
21
|
+
* Written failing on 2026-09-16, before the export exists; the change that follows
|
|
22
|
+
* extracts it from the fire caller's inline read (extract, do not copy).
|
|
23
|
+
*/
|
|
24
|
+
import { create } from "@bufbuild/protobuf";
|
|
25
|
+
import { describe, expect, it, vi } from "vitest";
|
|
26
|
+
|
|
27
|
+
import { IdentityAccountSchema } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
28
|
+
import { IdentityAccountProvisioningMode } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/enum_pb";
|
|
29
|
+
|
|
30
|
+
import { accountIdFor } from "../constants.js";
|
|
31
|
+
import { accountForStamp } from "../resolve.js";
|
|
32
|
+
import type { AccountsByCaller } from "../resolve.js";
|
|
33
|
+
import { fakeIdentityAccountStore } from "./support.js";
|
|
34
|
+
|
|
35
|
+
const SUBJECT = "auth0|carol";
|
|
36
|
+
const CAROL = accountIdFor(SUBJECT);
|
|
37
|
+
|
|
38
|
+
function seeded() {
|
|
39
|
+
const accounts = fakeIdentityAccountStore();
|
|
40
|
+
accounts.rows.set(
|
|
41
|
+
CAROL,
|
|
42
|
+
create(IdentityAccountSchema, {
|
|
43
|
+
metadata: { id: CAROL, name: "Carol Danvers" },
|
|
44
|
+
spec: {
|
|
45
|
+
idpId: SUBJECT,
|
|
46
|
+
email: "carol@example.com",
|
|
47
|
+
provisioningMode: IdentityAccountProvisioningMode.direct,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
return accounts;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("accountForStamp", () => {
|
|
55
|
+
it("an account-id stamp resolves by that id", async () => {
|
|
56
|
+
const account = await accountForStamp(seeded(), CAROL);
|
|
57
|
+
expect(account?.metadata?.id).toBe(CAROL);
|
|
58
|
+
expect(account?.spec?.email).toBe("carol@example.com");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("a raw-subject stamp (the 3.14.x shape) resolves through the direct lookup to the same account", async () => {
|
|
62
|
+
expect((await accountForStamp(seeded(), SUBJECT))?.metadata?.id).toBe(
|
|
63
|
+
CAROL,
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('the empty stamp is undefined with NO read — the store is never asked about ""', async () => {
|
|
68
|
+
const findById = vi.fn(async () => undefined);
|
|
69
|
+
const findDirectByIdpId = vi.fn(async () => undefined);
|
|
70
|
+
const accounts: AccountsByCaller = { findById, findDirectByIdpId };
|
|
71
|
+
expect(await accountForStamp(accounts, "")).toBeUndefined();
|
|
72
|
+
expect(findById).not.toHaveBeenCalled();
|
|
73
|
+
expect(findDirectByIdpId).not.toHaveBeenCalled();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it.each([
|
|
77
|
+
["the laptop's placeholder", "system"],
|
|
78
|
+
["a trusted-local email stamp", "operator@example.com"],
|
|
79
|
+
["a deleted account", accountIdFor("auth0|gone")],
|
|
80
|
+
])(
|
|
81
|
+
"%s is undefined — the caller decides what nobody means",
|
|
82
|
+
async (_label, stamp) => {
|
|
83
|
+
expect(await accountForStamp(seeded(), stamp)).toBeUndefined();
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
it("reads by id first, then by subject — two primary-key reads at most, in accountForCaller's order", async () => {
|
|
88
|
+
const calls: string[] = [];
|
|
89
|
+
const accounts: AccountsByCaller = {
|
|
90
|
+
findById: async (id) => {
|
|
91
|
+
calls.push(`id:${id}`);
|
|
92
|
+
return undefined;
|
|
93
|
+
},
|
|
94
|
+
findDirectByIdpId: async (idpId) => {
|
|
95
|
+
calls.push(`sub:${idpId}`);
|
|
96
|
+
return undefined;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
await accountForStamp(accounts, SUBJECT);
|
|
100
|
+
expect(calls).toEqual([`id:${SUBJECT}`, `sub:${SUBJECT}`]);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("a store fault propagates as the same error object, never a credential rejection", async () => {
|
|
104
|
+
const fault = new Error("connection reset");
|
|
105
|
+
const accounts: AccountsByCaller = {
|
|
106
|
+
findById: () => Promise.reject(fault),
|
|
107
|
+
findDirectByIdpId: async () => undefined,
|
|
108
|
+
};
|
|
109
|
+
await expect(accountForStamp(accounts, CAROL)).rejects.toBe(fault);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An account acting as itself — the ONE place server code builds the
|
|
3
|
+
* caller identity for a person it has resolved from a row rather than
|
|
4
|
+
* from the token that person presented. Two constructions, one shape:
|
|
5
|
+
* the account id is the principal, so the audit actor on every write
|
|
6
|
+
* names the account the way every other write names it, and email and
|
|
7
|
+
* display name ride along when the row knows them (the trusted-local
|
|
8
|
+
* identity's shape, pipeline/interceptors/auth.ts).
|
|
9
|
+
*
|
|
10
|
+
* `accountAsCaller(account)` — the IN-PROCESS lane: no issuer, no token,
|
|
11
|
+
* class `user`. Two consumers: the trusted-local boot ensure, which
|
|
12
|
+
* grants the operator ownership AS their account
|
|
13
|
+
* (domain/iampolicy/membership.ts), and the built-in schedule fire
|
|
14
|
+
* caller, which makes a fire act as the schedule's creator
|
|
15
|
+
* (authorization/schedule-fire-caller.ts). Both ride the in-process
|
|
16
|
+
* transport, whose interceptor stamps `origin: "in-process"` on top —
|
|
17
|
+
* the transport-trust marker is never set here.
|
|
18
|
+
*
|
|
19
|
+
* `accountAsRunnerCaller(account, rawToken)` — the WIRE lane: the
|
|
20
|
+
* runner-subject verifier (runnerauth/runner-subject-verifier.ts) admits
|
|
21
|
+
* the bearer of a run credential as the human whose run it is. Class
|
|
22
|
+
* `runner`, because the Authorizer's lane admission and the memory
|
|
23
|
+
* capture gate must tell a runner acting as a person from the person
|
|
24
|
+
* (extensions/identity.ts names the class for exactly this), and the
|
|
25
|
+
* verified token carried, because the provider's capabilities re-read the
|
|
26
|
+
* binding off `rawToken` (the cloud's own pattern) — one HMAC, no store
|
|
27
|
+
* read. No issuer: the server signed it.
|
|
28
|
+
*
|
|
29
|
+
* Why not a token for the in-process lane: open source mints no
|
|
30
|
+
* credential for a person the server is composing a request for; the
|
|
31
|
+
* identity is what the propagation header carries, and every consumer
|
|
32
|
+
* that reads a subject off the raw token (`idpIdOf`) is reached only
|
|
33
|
+
* through `accountForCaller`, which resolves this identity by its id
|
|
34
|
+
* first and never asks the token. The same holds for the runner lane:
|
|
35
|
+
* our token carries no `sub`, and nothing downstream needs one.
|
|
36
|
+
*/
|
|
37
|
+
import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
38
|
+
|
|
39
|
+
import type { CallerIdentity } from "../../extensions/identity.js";
|
|
40
|
+
|
|
41
|
+
export function accountAsCaller(account: IdentityAccount): CallerIdentity {
|
|
42
|
+
return {
|
|
43
|
+
...principalOf(account),
|
|
44
|
+
callerClass: "user",
|
|
45
|
+
issuer: "",
|
|
46
|
+
rawToken: "",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function accountAsRunnerCaller(
|
|
51
|
+
account: IdentityAccount,
|
|
52
|
+
rawToken: string,
|
|
53
|
+
): CallerIdentity {
|
|
54
|
+
if (rawToken === "") {
|
|
55
|
+
throw new Error(
|
|
56
|
+
"a runner caller carries the credential it presented — refusing to build one with none",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
...principalOf(account),
|
|
61
|
+
callerClass: "runner",
|
|
62
|
+
issuer: "",
|
|
63
|
+
rawToken,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The account id as principal, with the display identity the row knows. */
|
|
68
|
+
function principalOf(
|
|
69
|
+
account: IdentityAccount,
|
|
70
|
+
): Pick<CallerIdentity, "identityId" | "email" | "displayName"> {
|
|
71
|
+
const accountId = account.metadata?.id ?? "";
|
|
72
|
+
if (accountId === "") {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"identity account carries no id — refusing to build a caller for an empty principal",
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const email = account.spec?.email ?? "";
|
|
78
|
+
const displayName = account.metadata?.name ?? "";
|
|
79
|
+
return {
|
|
80
|
+
identityId: accountId,
|
|
81
|
+
...(email !== "" ? { email } : {}),
|
|
82
|
+
...(displayName !== "" ? { displayName } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -41,6 +41,19 @@
|
|
|
41
41
|
* cannot answer the same question two ways. A credential naming no
|
|
42
42
|
* subject is `undefined` with no second read: the store is never asked
|
|
43
43
|
* about "".
|
|
44
|
+
*
|
|
45
|
+
* The third reading is a ROW's creator stamp, `accountForStamp`: the
|
|
46
|
+
* account a `created_by.id` names, read the two ways a stamp has been
|
|
47
|
+
* written — as an account id (rows stamped since 3.15.0) and as the raw
|
|
48
|
+
* issuer subject (rows the 3.14.x verifiers stamped) — in
|
|
49
|
+
* `accountForCaller`'s order. Two lanes make the server act as the
|
|
50
|
+
* person a row names: the built-in schedule fire caller (a fire acts as
|
|
51
|
+
* the schedule's creator) and the runner-subject verifier (a run
|
|
52
|
+
* credential admits its bearer as the execution's creator). Stated here
|
|
53
|
+
* so they cannot resolve one stamp two ways; each decides for itself
|
|
54
|
+
* what "nobody" means (the fire caller's deterministic refusal, the
|
|
55
|
+
* verifier's liveness sentence), so this function answers `undefined`
|
|
56
|
+
* and never throws for it. The empty stamp is `undefined` with no read.
|
|
44
57
|
*/
|
|
45
58
|
import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
|
|
46
59
|
|
|
@@ -93,3 +106,21 @@ export async function accountForCaller(
|
|
|
93
106
|
}
|
|
94
107
|
return accounts.findDirectByIdpId(subject);
|
|
95
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The account a row's creator stamp names, or `undefined` when it names
|
|
112
|
+
* nobody (the laptop's `"system"`, a trusted-local email, a deleted
|
|
113
|
+
* account, the empty stamp). Faults propagate as they are.
|
|
114
|
+
*/
|
|
115
|
+
export async function accountForStamp(
|
|
116
|
+
accounts: AccountsByCaller,
|
|
117
|
+
stamp: string,
|
|
118
|
+
): Promise<IdentityAccount | undefined> {
|
|
119
|
+
if (stamp === "") {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return (
|
|
123
|
+
(await accounts.findById(stamp)) ??
|
|
124
|
+
(await accounts.findDirectByIdpId(stamp))
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -28,6 +28,7 @@ import { ExecutionContextSchema } from "@stigmer/protos/ai/stigmer/agentic/execu
|
|
|
28
28
|
|
|
29
29
|
import { createLogger } from "../../../boot/logger.js";
|
|
30
30
|
import { SecretService } from "../../../encryption/encryption.js";
|
|
31
|
+
import type { CallerIdentity } from "../../../extensions/identity.js";
|
|
31
32
|
import { newExecutionScopedRunnerCredentialProvider } from "../../../runnerauth/runner-credential-provider.js";
|
|
32
33
|
import { RunnerAuthService } from "../../../runnerauth/runnerauth.js";
|
|
33
34
|
import { SqliteStore } from "../../../store/sqlite/store.js";
|
|
@@ -41,6 +42,7 @@ import {
|
|
|
41
42
|
startBestEffortConnect,
|
|
42
43
|
} from "../connect.js";
|
|
43
44
|
import type { McpServerConnectDeps } from "../connect.js";
|
|
45
|
+
import { isConnectExecutionId } from "../connect-execution-id.js";
|
|
44
46
|
import { ManagedEnvironmentService } from "../oauth/managed-env.js";
|
|
45
47
|
import {
|
|
46
48
|
RUNNER_QUEUE_WARNING,
|
|
@@ -115,6 +117,8 @@ interface Harness {
|
|
|
115
117
|
deps: McpServerConnectDeps;
|
|
116
118
|
engine: FakeEngine;
|
|
117
119
|
ecCreates: number;
|
|
120
|
+
/** The caller each EC create was handed — the connect's person, never the server (the mcp-connect binding's stamp). */
|
|
121
|
+
ecCreators: CallerIdentity[];
|
|
118
122
|
ecDeletes: string[];
|
|
119
123
|
}
|
|
120
124
|
|
|
@@ -150,6 +154,7 @@ function makeHarness(options: FakeEngineOptions = {}): Harness {
|
|
|
150
154
|
const harness: Harness = {
|
|
151
155
|
engine,
|
|
152
156
|
ecCreates: 0,
|
|
157
|
+
ecCreators: [],
|
|
153
158
|
ecDeletes: [],
|
|
154
159
|
deps: {
|
|
155
160
|
store,
|
|
@@ -165,8 +170,9 @@ function makeHarness(options: FakeEngineOptions = {}): Harness {
|
|
|
165
170
|
},
|
|
166
171
|
},
|
|
167
172
|
executionContext: {
|
|
168
|
-
create: async () => {
|
|
173
|
+
create: async (_ec, caller) => {
|
|
169
174
|
harness.ecCreates += 1;
|
|
175
|
+
harness.ecCreators.push(caller);
|
|
170
176
|
return create(ExecutionContextSchema, {
|
|
171
177
|
metadata: { id: `ectx_${harness.ecCreates}` },
|
|
172
178
|
});
|
|
@@ -356,7 +362,7 @@ describe("connect (blocking lane)", () => {
|
|
|
356
362
|
expect(second.status?.toolApprovals[0]?.toolName).toBe("search");
|
|
357
363
|
});
|
|
358
364
|
|
|
359
|
-
it("creates the ephemeral EC from runtime_env, mints the decrypt token, and deletes the EC after settle", async () => {
|
|
365
|
+
it("creates the ephemeral EC from runtime_env AS THE CALLER, mints the decrypt token, and deletes the EC after settle", async () => {
|
|
360
366
|
const harness = makeHarness();
|
|
361
367
|
const server = await seedServer();
|
|
362
368
|
await connect(
|
|
@@ -366,9 +372,16 @@ describe("connect (blocking lane)", () => {
|
|
|
366
372
|
}),
|
|
367
373
|
);
|
|
368
374
|
expect(harness.ecCreates).toBe(1);
|
|
375
|
+
// The row's creator stamp is the connect token's person under the
|
|
376
|
+
// built-in posture (runnerauth/bound-execution.ts), so the connect
|
|
377
|
+
// hands the client the caller, never the server's own identity.
|
|
378
|
+
expect(harness.ecCreators).toEqual([testCaller]);
|
|
369
379
|
expect(harness.ecDeletes).toEqual(["ectx_1"]);
|
|
370
380
|
const input = harness.engine.startedInputs[0];
|
|
371
381
|
expect(input?.execution_context_id).toMatch(/^connect-mcps_test_/);
|
|
382
|
+
// The id is the one shape the runner-credential lane recognizes as a
|
|
383
|
+
// connect binding — builder and predicate share one module.
|
|
384
|
+
expect(isConnectExecutionId(input?.execution_context_id ?? "")).toBe(true);
|
|
372
385
|
// oss#535: the decrypt-lane token rides the payload.
|
|
373
386
|
expect(input?.execution_context_token).toBeTruthy();
|
|
374
387
|
});
|
|
@@ -584,6 +597,8 @@ describe("startConnect (async lane)", () => {
|
|
|
584
597
|
);
|
|
585
598
|
expect(result.metadata?.id).toBe(server.metadata!.id);
|
|
586
599
|
expect(harness.ecCreates).toBe(1);
|
|
600
|
+
// The async lane creates the EC as the caller too — one prepareConnect.
|
|
601
|
+
expect(harness.ecCreators).toEqual([testCaller]);
|
|
587
602
|
await vi.waitFor(() => expect(harness.ecDeletes).toEqual(["ectx_1"]));
|
|
588
603
|
});
|
|
589
604
|
});
|