@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
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evaluator — OpenFGA's check, over the built-in model and a tuple
|
|
3
|
+
* source, small because the model uses four rewrite forms and nothing
|
|
4
|
+
* else (model/rewrite.ts). `checkRelation(object, relation, person, context)`
|
|
5
|
+
* answers "does this person hold this relation on this object" the way
|
|
6
|
+
* the cloud's engine answers it over stored tuples, so the two editions
|
|
7
|
+
* share one meaning of authorization.
|
|
8
|
+
*
|
|
9
|
+
* The walk, in the order a `.fga` line reads:
|
|
10
|
+
* - `this`: the tuples on (object, relation). A tuple counts only if
|
|
11
|
+
* its subject's TYPE is in the line's restriction list — the check
|
|
12
|
+
* OpenFGA makes at write time, made here at read time, so a derived
|
|
13
|
+
* tuple the model no longer admits denies instead of allowing. An
|
|
14
|
+
* object subject matches when it names one of the person's aliases;
|
|
15
|
+
* a userset subject is resolved on its own object; the wildcard is
|
|
16
|
+
* honoured only under its condition (`allow_public` reads the
|
|
17
|
+
* context's `allow`; an unknown condition is a fault).
|
|
18
|
+
* - `computed`: the same object, another relation.
|
|
19
|
+
* - `from`: every object the tupleset relation links to (again within
|
|
20
|
+
* the tupleset line's type restriction), resolved for the relation.
|
|
21
|
+
* - `union`: the first true member wins; members are tried in the
|
|
22
|
+
* line's order, so the cheap arms the model lists first (the person's
|
|
23
|
+
* own owner tuple) are read before the hops.
|
|
24
|
+
*
|
|
25
|
+
* Bounds and faults. Every (object, relation) pair is resolved once per
|
|
26
|
+
* check (the memo — a diamond such as `owner` reached through `viewer`
|
|
27
|
+
* and through `can_edit` reads the source once). A pair re-entered while
|
|
28
|
+
* it is being resolved is a cycle in the declarations, which is a bug,
|
|
29
|
+
* and a resolution deeper than MAX_RESOLUTION_DEPTH is the same class of
|
|
30
|
+
* bug; both throw, because the alternative — a quiet `false` — would turn
|
|
31
|
+
* a broken transcript into a lockout nobody can see. A kind the model does
|
|
32
|
+
* not declare is a fault as the check's TARGET (the driver refuses
|
|
33
|
+
* unserved kinds before evaluation, so reaching here is a registry gap)
|
|
34
|
+
* and simply an object with no relations when reached through a tuple
|
|
35
|
+
* (`identity_provider#platform_user`, which no open-source tuple names).
|
|
36
|
+
* A relation the kind does not declare is `false` — the ruled answer for
|
|
37
|
+
* a wire question the model has no line for, where OpenFGA
|
|
38
|
+
* itself answers a validation error.
|
|
39
|
+
*
|
|
40
|
+
* The evaluator does no I/O of its own and knows no store: the source
|
|
41
|
+
* owns every read, and a fault it raises propagates through untouched,
|
|
42
|
+
* so the driver above can fold it into `unavailable` and never into a
|
|
43
|
+
* denial.
|
|
44
|
+
*/
|
|
45
|
+
import type { Model } from "./model/index.js";
|
|
46
|
+
import type { Rewrite, SubjectType } from "./model/rewrite.js";
|
|
47
|
+
import type {
|
|
48
|
+
CheckContext,
|
|
49
|
+
ObjectRef,
|
|
50
|
+
Person,
|
|
51
|
+
Subject,
|
|
52
|
+
TupleSource,
|
|
53
|
+
} from "./tuples.js";
|
|
54
|
+
import {
|
|
55
|
+
ACCOUNT_TYPE,
|
|
56
|
+
ALLOW_PUBLIC_CONDITION,
|
|
57
|
+
formatObjectRef,
|
|
58
|
+
pairKey,
|
|
59
|
+
} from "./tuples.js";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* OpenFGA's default resolution-depth limit (its `resolveNodeLimit`), so
|
|
63
|
+
* the bound here is the oracle's own and not a number chosen locally. The
|
|
64
|
+
* deepest real chain in the model is under ten: an instance's `viewer
|
|
65
|
+
* from default_of` to its blueprint, the blueprint's `admin from
|
|
66
|
+
* organization`, then the organization's four-rung ladder.
|
|
67
|
+
*/
|
|
68
|
+
export const MAX_RESOLUTION_DEPTH = 25;
|
|
69
|
+
|
|
70
|
+
export type EvaluationFault =
|
|
71
|
+
| "undeclared-target-kind"
|
|
72
|
+
| "resolution-depth-exceeded"
|
|
73
|
+
| "resolution-cycle"
|
|
74
|
+
| "unknown-condition";
|
|
75
|
+
|
|
76
|
+
/** A fault in the model or its evaluation — never a denial; the driver maps it to `unavailable`. */
|
|
77
|
+
export class AuthorizationEvaluationError extends Error {
|
|
78
|
+
readonly reason: EvaluationFault;
|
|
79
|
+
|
|
80
|
+
constructor(reason: EvaluationFault, message: string) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.name = "AuthorizationEvaluationError";
|
|
83
|
+
this.reason = reason;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface EvaluationDeps {
|
|
88
|
+
readonly model: Model;
|
|
89
|
+
readonly source: TupleSource;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function checkRelation(
|
|
93
|
+
deps: EvaluationDeps,
|
|
94
|
+
object: ObjectRef,
|
|
95
|
+
relation: string,
|
|
96
|
+
person: Person,
|
|
97
|
+
context: CheckContext,
|
|
98
|
+
): Promise<boolean> {
|
|
99
|
+
if (deps.model.byType(object.type) === undefined) {
|
|
100
|
+
throw new AuthorizationEvaluationError(
|
|
101
|
+
"undeclared-target-kind",
|
|
102
|
+
`no declaration for kind '${object.type}' (target ${formatObjectRef(object)})`,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return new Walk(deps, person, context).resolve(object, relation, 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** One check's state: the memo and the in-progress set, over one source. */
|
|
109
|
+
class Walk {
|
|
110
|
+
private readonly memo = new Map<string, Promise<boolean>>();
|
|
111
|
+
private readonly inProgress = new Set<string>();
|
|
112
|
+
|
|
113
|
+
constructor(
|
|
114
|
+
private readonly deps: EvaluationDeps,
|
|
115
|
+
private readonly person: Person,
|
|
116
|
+
private readonly context: CheckContext,
|
|
117
|
+
) {}
|
|
118
|
+
|
|
119
|
+
resolve(
|
|
120
|
+
object: ObjectRef,
|
|
121
|
+
relation: string,
|
|
122
|
+
depth: number,
|
|
123
|
+
): Promise<boolean> {
|
|
124
|
+
const key = pairKey(object, relation);
|
|
125
|
+
if (this.inProgress.has(key)) {
|
|
126
|
+
throw new AuthorizationEvaluationError(
|
|
127
|
+
"resolution-cycle",
|
|
128
|
+
`'${key}' re-entered while being resolved — the declarations cycle`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (depth > MAX_RESOLUTION_DEPTH) {
|
|
132
|
+
throw new AuthorizationEvaluationError(
|
|
133
|
+
"resolution-depth-exceeded",
|
|
134
|
+
`resolving '${key}' exceeded ${MAX_RESOLUTION_DEPTH} hops`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
const held = this.memo.get(key);
|
|
138
|
+
if (held !== undefined) {
|
|
139
|
+
return held;
|
|
140
|
+
}
|
|
141
|
+
const declaration = this.deps.model.byType(object.type);
|
|
142
|
+
const rewrite = declaration?.relations.get(relation);
|
|
143
|
+
if (declaration === undefined || rewrite === undefined) {
|
|
144
|
+
return Promise.resolve(false);
|
|
145
|
+
}
|
|
146
|
+
this.inProgress.add(key);
|
|
147
|
+
const result = this.evaluate(rewrite, object, relation, depth).finally(() =>
|
|
148
|
+
this.inProgress.delete(key),
|
|
149
|
+
);
|
|
150
|
+
this.memo.set(key, result);
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private async evaluate(
|
|
155
|
+
rewrite: Rewrite,
|
|
156
|
+
object: ObjectRef,
|
|
157
|
+
relation: string,
|
|
158
|
+
depth: number,
|
|
159
|
+
): Promise<boolean> {
|
|
160
|
+
switch (rewrite.node) {
|
|
161
|
+
case "this": {
|
|
162
|
+
const tuples = await this.deps.source.tuplesOf(object, relation);
|
|
163
|
+
for (const tuple of tuples) {
|
|
164
|
+
if (await this.subjectHolds(tuple.subject, rewrite.subjects, depth)) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
case "computed":
|
|
171
|
+
return this.resolve(object, rewrite.relation, depth + 1);
|
|
172
|
+
case "from": {
|
|
173
|
+
const linkTypes = this.objectTypesOf(object, rewrite.tupleset);
|
|
174
|
+
const links = await this.deps.source.tuplesOf(object, rewrite.tupleset);
|
|
175
|
+
for (const link of links) {
|
|
176
|
+
if (
|
|
177
|
+
link.subject.form === "object" &&
|
|
178
|
+
linkTypes.has(link.subject.object.type) &&
|
|
179
|
+
(await this.resolve(
|
|
180
|
+
link.subject.object,
|
|
181
|
+
rewrite.relation,
|
|
182
|
+
depth + 1,
|
|
183
|
+
))
|
|
184
|
+
) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
case "union": {
|
|
191
|
+
for (const member of rewrite.members) {
|
|
192
|
+
if (await this.evaluate(member, object, relation, depth)) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
default: {
|
|
199
|
+
const exhaustive: never = rewrite;
|
|
200
|
+
throw new Error(`unknown rewrite node: ${JSON.stringify(exhaustive)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Whether one direct tuple's subject reaches the person, within the line's type restriction. */
|
|
206
|
+
private async subjectHolds(
|
|
207
|
+
subject: Subject,
|
|
208
|
+
restriction: ReadonlyArray<SubjectType>,
|
|
209
|
+
depth: number,
|
|
210
|
+
): Promise<boolean> {
|
|
211
|
+
switch (subject.form) {
|
|
212
|
+
case "object":
|
|
213
|
+
return (
|
|
214
|
+
subject.object.type === ACCOUNT_TYPE &&
|
|
215
|
+
restriction.some(
|
|
216
|
+
(allowed) =>
|
|
217
|
+
allowed.form === "object" && allowed.type === ACCOUNT_TYPE,
|
|
218
|
+
) &&
|
|
219
|
+
this.person.aliases.has(subject.object.id)
|
|
220
|
+
);
|
|
221
|
+
case "userset":
|
|
222
|
+
return (
|
|
223
|
+
restriction.some(
|
|
224
|
+
(allowed) =>
|
|
225
|
+
allowed.form === "userset" &&
|
|
226
|
+
allowed.type === subject.object.type &&
|
|
227
|
+
allowed.relation === subject.relation,
|
|
228
|
+
) && (await this.resolve(subject.object, subject.relation, depth + 1))
|
|
229
|
+
);
|
|
230
|
+
case "wildcard": {
|
|
231
|
+
const allowed = restriction.some(
|
|
232
|
+
(entry) =>
|
|
233
|
+
entry.form === "wildcard" &&
|
|
234
|
+
entry.type === subject.type &&
|
|
235
|
+
entry.condition === subject.condition,
|
|
236
|
+
);
|
|
237
|
+
return allowed && this.conditionHolds(subject.condition);
|
|
238
|
+
}
|
|
239
|
+
default: {
|
|
240
|
+
const exhaustive: never = subject;
|
|
241
|
+
throw new Error(`unknown subject form: ${JSON.stringify(exhaustive)}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private conditionHolds(condition: string | undefined): boolean {
|
|
247
|
+
switch (condition) {
|
|
248
|
+
case ALLOW_PUBLIC_CONDITION:
|
|
249
|
+
return this.context.allow;
|
|
250
|
+
default:
|
|
251
|
+
throw new AuthorizationEvaluationError(
|
|
252
|
+
"unknown-condition",
|
|
253
|
+
`the model declares no condition '${String(condition)}'`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** The object types the tupleset line admits — `[organization]`, `[session]` — from its `this` nodes. */
|
|
259
|
+
private objectTypesOf(
|
|
260
|
+
object: ObjectRef,
|
|
261
|
+
tupleset: string,
|
|
262
|
+
): ReadonlySet<string> {
|
|
263
|
+
const rewrite = this.deps.model
|
|
264
|
+
.byType(object.type)
|
|
265
|
+
?.relations.get(tupleset);
|
|
266
|
+
const types = new Set<string>();
|
|
267
|
+
const collect = (node: Rewrite): void => {
|
|
268
|
+
if (node.node === "this") {
|
|
269
|
+
for (const subject of node.subjects) {
|
|
270
|
+
if (subject.form === "object") {
|
|
271
|
+
types.add(subject.type);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if (node.node === "union") {
|
|
275
|
+
node.members.forEach(collect);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
if (rewrite !== undefined) {
|
|
279
|
+
collect(rewrite);
|
|
280
|
+
}
|
|
281
|
+
return types;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The facts a stored row carries that its authorization tuples are
|
|
3
|
+
* derived from, as the built-in authorizer names them — the seam's
|
|
4
|
+
* `RowAuthorizationFacts` (extensions/resource-authorization.ts) with the
|
|
5
|
+
* kind beside them, because the derivation (derived-tuples.ts) reads the
|
|
6
|
+
* kind's `kind_meta` and names the object by its type.
|
|
7
|
+
*
|
|
8
|
+
* The facts have two producers and one resolver. A LOADED row (the
|
|
9
|
+
* point-check driver's path, `rowFactsOf`) and a list lane's candidate
|
|
10
|
+
* (`ListEntryMeta`, built by the lanes' shared helper; `rowFactsOfEntry`)
|
|
11
|
+
* both read through pipeline/steps/authorization-facts.ts — the read-time
|
|
12
|
+
* twin of the tuple lifecycle's create-time resolution, lenient where that
|
|
13
|
+
* one throws (a legacy row's missing organization is a fact, not a fault),
|
|
14
|
+
* and pinned equal to it in __tests__/facts.test.ts. Naming the shape once
|
|
15
|
+
* is what lets the derivation stay one function and what states exactly
|
|
16
|
+
* which facts a list candidate must carry: a candidate's facts ARE these,
|
|
17
|
+
* so a list evaluates the model over what the lane already decoded and
|
|
18
|
+
* never reads a candidate's row a second time.
|
|
19
|
+
*/
|
|
20
|
+
import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
21
|
+
|
|
22
|
+
import type { RowAuthorizationFacts } from "../extensions/resource-authorization.js";
|
|
23
|
+
import { rowAuthorizationFactsOf } from "../pipeline/steps/authorization-facts.js";
|
|
24
|
+
|
|
25
|
+
export interface RowFacts extends RowAuthorizationFacts {
|
|
26
|
+
readonly kind: ApiResourceKind;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The facts of a loaded row of `kind`. */
|
|
30
|
+
export function rowFactsOf(kind: ApiResourceKind, row: object): RowFacts {
|
|
31
|
+
return { kind, ...rowAuthorizationFactsOf(kind, row) };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The facts a list candidate of `kind` carries — the same facts, already read by the lane's helper. */
|
|
35
|
+
export function rowFactsOfEntry(
|
|
36
|
+
kind: ApiResourceKind,
|
|
37
|
+
entry: RowAuthorizationFacts,
|
|
38
|
+
): RowFacts {
|
|
39
|
+
return {
|
|
40
|
+
kind,
|
|
41
|
+
id: entry.id,
|
|
42
|
+
org: entry.org,
|
|
43
|
+
visibility: entry.visibility,
|
|
44
|
+
createdBy: entry.createdBy,
|
|
45
|
+
parentLinks: entry.parentLinks,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lane admission over the Authorizer seam — open source's rendering of
|
|
3
|
+
* the cloud's decorator (stigmer-cloud `authorizer/lane-admission.ts`,
|
|
4
|
+
* stigmer-cloud#709), composed around the built-in Authorizer under the
|
|
5
|
+
* built-in authorization posture (boot/compose.ts).
|
|
6
|
+
*
|
|
7
|
+
* The OSS AuthorizeRunTarget step asks the Authorizer, for every caller
|
|
8
|
+
* but the internal class, whether the caller may run what a session or
|
|
9
|
+
* execution targets — the run-gate checks (`isRunGateCheck`, the
|
|
10
|
+
* OSS-owned definition of that set: `can_execute` on the blueprints and
|
|
11
|
+
* instances, `can_create_execution_in` on a session). A runner acting
|
|
12
|
+
* for a WORKFLOW execution creates the workflow's child agent executions
|
|
13
|
+
* (the `agent_call` activity), and it does so AS THE HUMAN whose workflow
|
|
14
|
+
* it is (runnerauth/runner-subject-verifier.ts). Checked as that human,
|
|
15
|
+
* a member running an organization-visible workflow that calls another
|
|
16
|
+
* member's private agent would be refused at the child create — but
|
|
17
|
+
* the parent workflow execution already passed its own run gate, and
|
|
18
|
+
* the human's visibility of the agents a shared workflow calls is not
|
|
19
|
+
* the question. The cloud admits its `workflow_sandbox` lane on exactly
|
|
20
|
+
* these checks for exactly this reason; this decorator gives an
|
|
21
|
+
* enforcing self-host the same answer, so a workflow behaves the same in
|
|
22
|
+
* both editions (the parent program's rule: nothing diverges silently).
|
|
23
|
+
*
|
|
24
|
+
* Why a predicate and not a class set: the cloud keys its decorator on
|
|
25
|
+
* `callerClass` because there the class IS the token type. In open
|
|
26
|
+
* source the class is `runner` for every bound execution, and the
|
|
27
|
+
* binding's KIND lives in the token, readable by the one function that
|
|
28
|
+
* interprets runner tokens (`isWorkflowBoundRunner` in
|
|
29
|
+
* runnerauth/built-in-runner-credential-provider.ts). Handing that
|
|
30
|
+
* reading in as `isAdmittedLane` keeps this module free of token
|
|
31
|
+
* knowledge and lets the cloud adopt the same shape later without a
|
|
32
|
+
* second class name. An AGENT-bound runner is NOT admitted: a subagent
|
|
33
|
+
* create is checked as the human, the cloud's `sandbox` posture.
|
|
34
|
+
*
|
|
35
|
+
* Narrow by construction: an admitted lane on any NON-run-gate check,
|
|
36
|
+
* and any other caller on any check, delegate untouched. The cloud's
|
|
37
|
+
* header records one caveat — a human who can view a workflow execution
|
|
38
|
+
* can exchange for its token and replay it against the run gate. Open
|
|
39
|
+
* source has no such caveat: under this posture the exchange is a mint
|
|
40
|
+
* gate that answers only the run's own person (the built-in provider's
|
|
41
|
+
* exchangeScopedToken, runnerauth/built-in-runner-credential-provider.ts),
|
|
42
|
+
* so the only human who can hold a workflow's credential is the one whose
|
|
43
|
+
* workflow it is — and their own run gate already passed.
|
|
44
|
+
*/
|
|
45
|
+
import type { CallerIdentity } from "../extensions/identity.js";
|
|
46
|
+
import type {
|
|
47
|
+
Authorizer,
|
|
48
|
+
AuthzCheck,
|
|
49
|
+
AuthzDecision,
|
|
50
|
+
} from "../extensions/authorizer.js";
|
|
51
|
+
import { isRunGateCheck } from "../pipeline/steps/authorize-run-target.js";
|
|
52
|
+
|
|
53
|
+
const ADMITTED: AuthzDecision = { kind: "allow" };
|
|
54
|
+
|
|
55
|
+
/** Whether `caller` is a lane whose admission to CREATE a run was decided upstream. */
|
|
56
|
+
export type LaneAdmissionPredicate = (caller: CallerIdentity) => boolean;
|
|
57
|
+
|
|
58
|
+
export function newLaneAdmittedAuthorizer(
|
|
59
|
+
inner: Authorizer,
|
|
60
|
+
isAdmittedLane: LaneAdmissionPredicate,
|
|
61
|
+
): Authorizer {
|
|
62
|
+
return {
|
|
63
|
+
authorize(
|
|
64
|
+
caller: CallerIdentity,
|
|
65
|
+
check: AuthzCheck,
|
|
66
|
+
): Promise<AuthzDecision> {
|
|
67
|
+
if (isRunGateCheck(check) && isAdmittedLane(caller)) {
|
|
68
|
+
return Promise.resolve(ADMITTED);
|
|
69
|
+
}
|
|
70
|
+
return inner.authorize(caller, check);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in list read scope — open source's driver for the list-read
|
|
3
|
+
* seam (extensions/list-read-scope.ts), composed under the built-in
|
|
4
|
+
* posture (posture.ts). The cloud's driver asks OpenFGA `can_view` for
|
|
5
|
+
* every candidate a list lane offers and ListObjects for the enumeration
|
|
6
|
+
* lanes; this one asks the same question of the same model, evaluated by
|
|
7
|
+
* the same evaluator the built-in Authorizer uses (evaluator.ts), over
|
|
8
|
+
* the tuples each candidate's row would have had — derived from the
|
|
9
|
+
* facts the candidate already carries (`ListEntryMeta` is the row's
|
|
10
|
+
* `RowAuthorizationFacts`; facts.ts), so a list never reads a candidate's
|
|
11
|
+
* row a second time. A self-host's lists show a person exactly what a
|
|
12
|
+
* `get` would let them read.
|
|
13
|
+
*
|
|
14
|
+
* Both verbs ask under the LISTING context, `allow: false` — the public
|
|
15
|
+
* wildcard suppressed, the cloud's own posture (its Java
|
|
16
|
+
* listAuthorizedResourceIds set it): a legacy PUBLIC row reads for any
|
|
17
|
+
* signed-in person on a point check and never expands into an outsider's
|
|
18
|
+
* listing; the organization's own people still reach it through the
|
|
19
|
+
* org-viewer shape public also emits.
|
|
20
|
+
*
|
|
21
|
+
* - `restrictListEntries`: one derived source for the caller, seeded
|
|
22
|
+
* with every candidate's facts; one `checkRelation` per unique id —
|
|
23
|
+
* one evaluator walk per candidate, never shared, because the walk's
|
|
24
|
+
* memo and its cycle detector are one object and a shared walk would
|
|
25
|
+
* read a second candidate's in-flight resolution of the same pair as
|
|
26
|
+
* a cycle. The candidates run concurrently: the only shared state is
|
|
27
|
+
* the source, whose promise memo dedupes the loads (the person's rows
|
|
28
|
+
* once; each distinct parent once — an execution list reads its
|
|
29
|
+
* distinct SESSIONS, entry 9's parent-check exactly). The kept set is
|
|
30
|
+
* a subset of the offered ids; order is the lane's.
|
|
31
|
+
* - `authorizedResourceIds`: the kind scanned, decoded and evaluated
|
|
32
|
+
* the same way. There is no tuple index to enumerate from and the
|
|
33
|
+
* answer is genuinely not "everything" (private blueprints exist), so
|
|
34
|
+
* the verb costs one scan of the kind — the console library rides
|
|
35
|
+
* it (blueprints have no list RPC; the library is a search), measured
|
|
36
|
+
* and recorded rather than assumed. A row that does not decode is
|
|
37
|
+
* skipped with a warning, the `loadAll*` idiom every lane follows: no
|
|
38
|
+
* lane can show it either.
|
|
39
|
+
*
|
|
40
|
+
* The `internal` class — the server acting as itself over the in-process
|
|
41
|
+
* transport — keeps every offered id and enumerates every id of the kind:
|
|
42
|
+
* the in-process authorization skip (pipeline/interceptors/auth.ts, ruling
|
|
43
|
+
* Q4) applied to a list answer, as the built-in directory applies it to a
|
|
44
|
+
* directory answer. No in-process edge reaches a list lane today; the arm
|
|
45
|
+
* is pinned so a future one meets the same rule every other lane keeps.
|
|
46
|
+
*
|
|
47
|
+
* Faults THROW and are never an empty answer (the seam: an empty set means
|
|
48
|
+
* "authorized to see nothing"; an outage is the pipeline's sanitized
|
|
49
|
+
* INTERNAL). A kind the model does not declare is a consumer bug by the
|
|
50
|
+
* seam's contract and faults through the evaluator, loud; the model
|
|
51
|
+
* declares exactly the open-source tier, so no served lane can reach it.
|
|
52
|
+
*
|
|
53
|
+
* Logging. One debug line per call — kind, offered, kept, elapsed — what
|
|
54
|
+
* an operator needs to answer "why is Alice's list short" beside the
|
|
55
|
+
* Authorizer's per-denial lines; never the token.
|
|
56
|
+
*/
|
|
57
|
+
import { fromBinary } from "@bufbuild/protobuf";
|
|
58
|
+
|
|
59
|
+
import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
60
|
+
|
|
61
|
+
import type { Logger } from "../boot/logger.js";
|
|
62
|
+
import type { IamPolicyStore } from "../domain/iampolicy/store.js";
|
|
63
|
+
import type { CallerIdentity } from "../extensions/identity.js";
|
|
64
|
+
import type {
|
|
65
|
+
ListEntryMeta,
|
|
66
|
+
ListReadScope,
|
|
67
|
+
} from "../extensions/list-read-scope.js";
|
|
68
|
+
import { kindEnumName } from "../pipeline/apiresource-meta.js";
|
|
69
|
+
import type { Store } from "../store/interface.js";
|
|
70
|
+
import { newDerivedTupleSource } from "./derived-tuples.js";
|
|
71
|
+
import { AuthorizationEvaluationError, checkRelation } from "./evaluator.js";
|
|
72
|
+
import type { RowFacts } from "./facts.js";
|
|
73
|
+
import { rowFactsOf, rowFactsOfEntry } from "./facts.js";
|
|
74
|
+
import type { Model } from "./model/index.js";
|
|
75
|
+
import { builtInModel } from "./model/index.js";
|
|
76
|
+
import type { KindDeclaration } from "./model/rewrite.js";
|
|
77
|
+
import type { AccountsByCaller } from "./person.js";
|
|
78
|
+
import { resolvePerson } from "./person.js";
|
|
79
|
+
import type { CheckContext, ObjectRef, Person } from "./tuples.js";
|
|
80
|
+
|
|
81
|
+
/** The relation every list lane reads through (the cloud's LIST_RELATION). */
|
|
82
|
+
const LIST_RELATION = "can_view";
|
|
83
|
+
|
|
84
|
+
/** The listing context: the public wildcard suppressed (the module header). */
|
|
85
|
+
const LISTING: CheckContext = { allow: false };
|
|
86
|
+
|
|
87
|
+
export interface BuiltInListReadScopeDeps {
|
|
88
|
+
readonly store: Store;
|
|
89
|
+
/** The port the grant path writes through — the person's rows are read from the same instance. */
|
|
90
|
+
readonly policies: IamPolicyStore;
|
|
91
|
+
/** The account port: the caller's account, and the parent hops that land on one. */
|
|
92
|
+
readonly accounts: AccountsByCaller;
|
|
93
|
+
readonly logger: Logger;
|
|
94
|
+
/** The declarations to evaluate; the built-in model unless a test says otherwise. */
|
|
95
|
+
readonly model?: Model;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function newBuiltInListReadScope(
|
|
99
|
+
deps: BuiltInListReadScopeDeps,
|
|
100
|
+
): ListReadScope {
|
|
101
|
+
const model = deps.model ?? builtInModel;
|
|
102
|
+
|
|
103
|
+
/** The candidates the caller may view, each answered by its own walk over one seeded source. */
|
|
104
|
+
async function visibleAmong(
|
|
105
|
+
caller: CallerIdentity,
|
|
106
|
+
kind: ApiResourceKind,
|
|
107
|
+
candidates: ReadonlyArray<RowFacts>,
|
|
108
|
+
): Promise<ReadonlySet<string>> {
|
|
109
|
+
if (candidates.length === 0) {
|
|
110
|
+
return new Set();
|
|
111
|
+
}
|
|
112
|
+
const started = performance.now();
|
|
113
|
+
const person: Person = await resolvePerson(deps.accounts, caller);
|
|
114
|
+
const source = newDerivedTupleSource(
|
|
115
|
+
{
|
|
116
|
+
store: deps.store,
|
|
117
|
+
policies: deps.policies,
|
|
118
|
+
accounts: deps.accounts,
|
|
119
|
+
model,
|
|
120
|
+
},
|
|
121
|
+
person,
|
|
122
|
+
{ facts: candidates },
|
|
123
|
+
);
|
|
124
|
+
const type = kindEnumName(kind);
|
|
125
|
+
const answers = await Promise.all(
|
|
126
|
+
candidates.map(async (facts) => {
|
|
127
|
+
const object: ObjectRef = { type, id: facts.id };
|
|
128
|
+
const allowed = await checkRelation(
|
|
129
|
+
{ model, source },
|
|
130
|
+
object,
|
|
131
|
+
LIST_RELATION,
|
|
132
|
+
person,
|
|
133
|
+
LISTING,
|
|
134
|
+
);
|
|
135
|
+
return allowed ? facts.id : undefined;
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
const kept = new Set<string>();
|
|
139
|
+
for (const id of answers) {
|
|
140
|
+
if (id !== undefined) {
|
|
141
|
+
kept.add(id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
deps.logger.debug("list scope evaluated candidates", {
|
|
145
|
+
account: person.accountId,
|
|
146
|
+
kind: type,
|
|
147
|
+
offered: candidates.length,
|
|
148
|
+
kept: kept.size,
|
|
149
|
+
elapsedMs: Math.round(performance.now() - started),
|
|
150
|
+
});
|
|
151
|
+
return kept;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** The declaration a verb evaluates against; an undeclared kind is the evaluator's own fault, raised before any read. */
|
|
155
|
+
function requireDeclared(kind: ApiResourceKind): KindDeclaration {
|
|
156
|
+
const declaration = model.byKind(kind);
|
|
157
|
+
if (declaration === undefined) {
|
|
158
|
+
throw new AuthorizationEvaluationError(
|
|
159
|
+
"undeclared-target-kind",
|
|
160
|
+
`no declaration for kind '${kindEnumName(kind)}' — a list lane asked the scope about a kind the model does not declare`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return declaration;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Every row of `kind` the store holds, as facts; a row that does not decode is skipped. */
|
|
167
|
+
async function everyRowOf(declaration: KindDeclaration): Promise<RowFacts[]> {
|
|
168
|
+
const kind = declaration.kind;
|
|
169
|
+
const rows = await deps.store.listResources(kind);
|
|
170
|
+
const facts: RowFacts[] = [];
|
|
171
|
+
for (const bytes of rows) {
|
|
172
|
+
try {
|
|
173
|
+
facts.push(rowFactsOf(kind, fromBinary(declaration.schema, bytes)));
|
|
174
|
+
} catch (error) {
|
|
175
|
+
deps.logger.warn("list scope skipped a row that does not decode", {
|
|
176
|
+
kind: kindEnumName(kind),
|
|
177
|
+
error: error instanceof Error ? error.message : String(error),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return facts;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
async restrictListEntries(
|
|
186
|
+
caller: CallerIdentity,
|
|
187
|
+
kind: ApiResourceKind,
|
|
188
|
+
entries: ReadonlyArray<ListEntryMeta>,
|
|
189
|
+
): Promise<ReadonlySet<string>> {
|
|
190
|
+
requireDeclared(kind);
|
|
191
|
+
// One candidate per unique id: a lane offers each row once, and a
|
|
192
|
+
// duplicate would only spend a walk to learn the same answer.
|
|
193
|
+
const unique = new Map<string, RowFacts>();
|
|
194
|
+
for (const entry of entries) {
|
|
195
|
+
if (!unique.has(entry.id)) {
|
|
196
|
+
unique.set(entry.id, rowFactsOfEntry(kind, entry));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (caller.callerClass === "internal") {
|
|
200
|
+
return new Set(unique.keys());
|
|
201
|
+
}
|
|
202
|
+
return visibleAmong(caller, kind, [...unique.values()]);
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
async authorizedResourceIds(
|
|
206
|
+
caller: CallerIdentity,
|
|
207
|
+
kind: ApiResourceKind,
|
|
208
|
+
): Promise<ReadonlySet<string>> {
|
|
209
|
+
const candidates = await everyRowOf(requireDeclared(kind));
|
|
210
|
+
if (caller.callerClass === "internal") {
|
|
211
|
+
return new Set(candidates.map((facts) => facts.id));
|
|
212
|
+
}
|
|
213
|
+
return visibleAmong(caller, kind, candidates);
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|