@cleocode/core 2026.6.13 → 2026.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/ops.d.ts +4 -0
- package/dist/admin/ops.d.ts.map +1 -1
- package/dist/check/index.d.ts +12 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +12 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/pr-gate.d.ts +179 -0
- package/dist/check/pr-gate.d.ts.map +1 -0
- package/dist/check/pr-gate.js +366 -0
- package/dist/check/pr-gate.js.map +1 -0
- package/dist/conduit/delivery-router.d.ts +134 -0
- package/dist/conduit/delivery-router.d.ts.map +1 -0
- package/dist/conduit/delivery-router.js +0 -0
- package/dist/conduit/delivery-router.js.map +1 -0
- package/dist/conduit/index.d.ts +5 -2
- package/dist/conduit/index.d.ts.map +1 -1
- package/dist/conduit/index.js +5 -2
- package/dist/conduit/index.js.map +1 -1
- package/dist/conduit/local-tui-adapter.d.ts +89 -0
- package/dist/conduit/local-tui-adapter.d.ts.map +1 -0
- package/dist/conduit/local-tui-adapter.js +225 -0
- package/dist/conduit/local-tui-adapter.js.map +1 -0
- package/dist/config/registry.d.ts +54 -0
- package/dist/config/registry.d.ts.map +1 -1
- package/dist/config/registry.js +94 -2
- package/dist/config/registry.js.map +1 -1
- package/dist/deriver/queue-manager.d.ts +30 -2
- package/dist/deriver/queue-manager.d.ts.map +1 -1
- package/dist/deriver/queue-manager.js +54 -9
- package/dist/deriver/queue-manager.js.map +1 -1
- package/dist/dispatch/config-domain-handler.d.ts +125 -0
- package/dist/dispatch/config-domain-handler.d.ts.map +1 -0
- package/dist/dispatch/config-domain-handler.js +160 -0
- package/dist/dispatch/config-domain-handler.js.map +1 -0
- package/dist/dispatch/contracts/input-contracts.d.ts.map +1 -1
- package/dist/dispatch/contracts/input-contracts.js +19 -1
- package/dist/dispatch/contracts/input-contracts.js.map +1 -1
- package/dist/docs/export-document.js +3704 -680
- package/dist/docs/export-document.js.map +3 -3
- package/dist/gateway-client/client.d.ts +123 -0
- package/dist/gateway-client/client.d.ts.map +1 -0
- package/dist/gateway-client/client.js +93 -0
- package/dist/gateway-client/client.js.map +1 -0
- package/dist/gateway-client/generated/client/client.gen.d.ts +3 -0
- package/dist/gateway-client/generated/client/client.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/client/client.gen.js +217 -0
- package/dist/gateway-client/generated/client/client.gen.js.map +1 -0
- package/dist/gateway-client/generated/client/index.d.ts +11 -0
- package/dist/gateway-client/generated/client/index.d.ts.map +1 -0
- package/dist/gateway-client/generated/client/index.js +7 -0
- package/dist/gateway-client/generated/client/index.js.map +1 -0
- package/dist/gateway-client/generated/client/types.gen.d.ts +121 -0
- package/dist/gateway-client/generated/client/types.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/client/types.gen.js +3 -0
- package/dist/gateway-client/generated/client/types.gen.js.map +1 -0
- package/dist/gateway-client/generated/client/utils.gen.d.ts +38 -0
- package/dist/gateway-client/generated/client/utils.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/client/utils.gen.js +229 -0
- package/dist/gateway-client/generated/client/utils.gen.js.map +1 -0
- package/dist/gateway-client/generated/client.gen.d.ts +13 -0
- package/dist/gateway-client/generated/client.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/client.gen.js +4 -0
- package/dist/gateway-client/generated/client.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/auth.gen.d.ts +26 -0
- package/dist/gateway-client/generated/core/auth.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/auth.gen.js +15 -0
- package/dist/gateway-client/generated/core/auth.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/bodySerializer.gen.d.ts +26 -0
- package/dist/gateway-client/generated/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/bodySerializer.gen.js +58 -0
- package/dist/gateway-client/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/params.gen.d.ts +44 -0
- package/dist/gateway-client/generated/core/params.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/params.gen.js +101 -0
- package/dist/gateway-client/generated/core/params.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/pathSerializer.gen.d.ts +34 -0
- package/dist/gateway-client/generated/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/pathSerializer.gen.js +107 -0
- package/dist/gateway-client/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/gateway-client/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/queryKeySerializer.gen.js +93 -0
- package/dist/gateway-client/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/gateway-client/generated/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/serverSentEvents.gen.js +133 -0
- package/dist/gateway-client/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/types.gen.d.ts +84 -0
- package/dist/gateway-client/generated/core/types.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/types.gen.js +3 -0
- package/dist/gateway-client/generated/core/types.gen.js.map +1 -0
- package/dist/gateway-client/generated/core/utils.gen.d.ts +20 -0
- package/dist/gateway-client/generated/core/utils.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/core/utils.gen.js +88 -0
- package/dist/gateway-client/generated/core/utils.gen.js.map +1 -0
- package/dist/gateway-client/generated/index.d.ts +3 -0
- package/dist/gateway-client/generated/index.d.ts.map +1 -0
- package/dist/gateway-client/generated/index.js +3 -0
- package/dist/gateway-client/generated/index.js.map +1 -0
- package/dist/gateway-client/generated/namespaces.gen.d.ts +512 -0
- package/dist/gateway-client/generated/namespaces.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/namespaces.gen.js +521 -0
- package/dist/gateway-client/generated/namespaces.gen.js.map +1 -0
- package/dist/gateway-client/generated/sdk.gen.d.ts +1780 -0
- package/dist/gateway-client/generated/sdk.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/sdk.gen.js +3811 -0
- package/dist/gateway-client/generated/sdk.gen.js.map +1 -0
- package/dist/gateway-client/generated/types.gen.d.ts +14681 -0
- package/dist/gateway-client/generated/types.gen.d.ts.map +1 -0
- package/dist/gateway-client/generated/types.gen.js +3 -0
- package/dist/gateway-client/generated/types.gen.js.map +1 -0
- package/dist/gateway-client/index.d.ts +27 -0
- package/dist/gateway-client/index.d.ts.map +1 -0
- package/dist/gateway-client/index.js +25 -0
- package/dist/gateway-client/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +28 -0
- package/dist/init.js.map +1 -1
- package/dist/internal.d.ts +10 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +18 -1
- package/dist/internal.js.map +1 -1
- package/dist/llm/catalog-model-resolver.d.ts +19 -0
- package/dist/llm/catalog-model-resolver.d.ts.map +1 -1
- package/dist/llm/catalog-model-resolver.js +36 -0
- package/dist/llm/catalog-model-resolver.js.map +1 -1
- package/dist/llm/catalog-resolver.d.ts +112 -0
- package/dist/llm/catalog-resolver.d.ts.map +1 -0
- package/dist/llm/catalog-resolver.js +207 -0
- package/dist/llm/catalog-resolver.js.map +1 -0
- package/dist/llm/catalog-seeder.d.ts +96 -0
- package/dist/llm/catalog-seeder.d.ts.map +1 -0
- package/dist/llm/catalog-seeder.js +189 -0
- package/dist/llm/catalog-seeder.js.map +1 -0
- package/dist/llm/cli-ops.js +5 -5
- package/dist/llm/cli-ops.js.map +1 -1
- package/dist/llm/complexity-classifier.d.ts +208 -0
- package/dist/llm/complexity-classifier.d.ts.map +1 -0
- package/dist/llm/complexity-classifier.js +359 -0
- package/dist/llm/complexity-classifier.js.map +1 -0
- package/dist/llm/credential-pool.d.ts +2 -0
- package/dist/llm/credential-pool.d.ts.map +1 -1
- package/dist/llm/credential-pool.js +5 -2
- package/dist/llm/credential-pool.js.map +1 -1
- package/dist/llm/credentials-store.d.ts +10 -14
- package/dist/llm/credentials-store.d.ts.map +1 -1
- package/dist/llm/credentials-store.js.map +1 -1
- package/dist/llm/entity-ops.d.ts +299 -0
- package/dist/llm/entity-ops.d.ts.map +1 -0
- package/dist/llm/entity-ops.js +441 -0
- package/dist/llm/entity-ops.js.map +1 -0
- package/dist/llm/index.d.ts +15 -0
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +8 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/llm-queue-admit.d.ts +118 -0
- package/dist/llm/llm-queue-admit.d.ts.map +1 -0
- package/dist/llm/llm-queue-admit.js +275 -0
- package/dist/llm/llm-queue-admit.js.map +1 -0
- package/dist/llm/oauth/device-code.d.ts.map +1 -1
- package/dist/llm/oauth/device-code.js +2 -8
- package/dist/llm/oauth/device-code.js.map +1 -1
- package/dist/llm/oauth/google-pkce.d.ts.map +1 -1
- package/dist/llm/oauth/google-pkce.js +2 -18
- package/dist/llm/oauth/google-pkce.js.map +1 -1
- package/dist/llm/oauth/pkce.d.ts +70 -0
- package/dist/llm/oauth/pkce.d.ts.map +1 -1
- package/dist/llm/oauth/pkce.js +106 -29
- package/dist/llm/oauth/pkce.js.map +1 -1
- package/dist/llm/onboarding/front-door.d.ts +146 -0
- package/dist/llm/onboarding/front-door.d.ts.map +1 -0
- package/dist/llm/onboarding/front-door.js +153 -0
- package/dist/llm/onboarding/front-door.js.map +1 -0
- package/dist/llm/onboarding/login-engine.d.ts +175 -0
- package/dist/llm/onboarding/login-engine.d.ts.map +1 -0
- package/dist/llm/onboarding/login-engine.js +286 -0
- package/dist/llm/onboarding/login-engine.js.map +1 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts +23 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts.map +1 -1
- package/dist/llm/pi/pi-gondolin-env.js +2 -2
- package/dist/llm/pi/pi-gondolin-env.js.map +1 -1
- package/dist/llm/plugin-facade.js +3853 -814
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/llm/provider-registry/builtin/anthropic.d.ts.map +1 -1
- package/dist/llm/provider-registry/builtin/anthropic.js +23 -10
- package/dist/llm/provider-registry/builtin/anthropic.js.map +1 -1
- package/dist/llm/provider-registry/provider-alias.d.ts +62 -0
- package/dist/llm/provider-registry/provider-alias.d.ts.map +1 -0
- package/dist/llm/provider-registry/provider-alias.js +85 -0
- package/dist/llm/provider-registry/provider-alias.js.map +1 -0
- package/dist/llm/provider-registry/provider-defs.d.ts +45 -0
- package/dist/llm/provider-registry/provider-defs.d.ts.map +1 -0
- package/dist/llm/provider-registry/provider-defs.js +145 -0
- package/dist/llm/provider-registry/provider-defs.js.map +1 -0
- package/dist/llm/provider-registry/provider-seed.d.ts +78 -0
- package/dist/llm/provider-registry/provider-seed.d.ts.map +1 -0
- package/dist/llm/provider-registry/provider-seed.js +113 -0
- package/dist/llm/provider-registry/provider-seed.js.map +1 -0
- package/dist/llm/role-executor.d.ts.map +1 -1
- package/dist/llm/role-executor.js +36 -0
- package/dist/llm/role-executor.js.map +1 -1
- package/dist/llm/role-resolver.d.ts.map +1 -1
- package/dist/llm/role-resolver.js +9 -2
- package/dist/llm/role-resolver.js.map +1 -1
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +73 -22
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/memory/learnings.d.ts +4 -0
- package/dist/memory/learnings.d.ts.map +1 -1
- package/dist/memory/patterns.d.ts +4 -0
- package/dist/memory/patterns.d.ts.map +1 -1
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -0
- package/dist/metrics/index.js.map +1 -1
- package/dist/orchestration/spawn.d.ts +89 -0
- package/dist/orchestration/spawn.d.ts.map +1 -1
- package/dist/orchestration/spawn.js +68 -0
- package/dist/orchestration/spawn.js.map +1 -1
- package/dist/playbooks/cantbook-profile.d.ts +96 -0
- package/dist/playbooks/cantbook-profile.d.ts.map +1 -0
- package/dist/playbooks/cantbook-profile.js +97 -0
- package/dist/playbooks/cantbook-profile.js.map +1 -0
- package/dist/playbooks/guarded-deterministic-runner.d.ts +153 -0
- package/dist/playbooks/guarded-deterministic-runner.d.ts.map +1 -0
- package/dist/playbooks/guarded-deterministic-runner.js +155 -0
- package/dist/playbooks/guarded-deterministic-runner.js.map +1 -0
- package/dist/playbooks/index.d.ts +2 -0
- package/dist/playbooks/index.d.ts.map +1 -1
- package/dist/playbooks/index.js +10 -0
- package/dist/playbooks/index.js.map +1 -1
- package/dist/playbooks/pi-runner-wiring.d.ts +75 -0
- package/dist/playbooks/pi-runner-wiring.d.ts.map +1 -0
- package/dist/playbooks/pi-runner-wiring.js +82 -0
- package/dist/playbooks/pi-runner-wiring.js.map +1 -0
- package/dist/runtime/openapi/generate-openapi.d.ts +211 -0
- package/dist/runtime/openapi/generate-openapi.d.ts.map +1 -0
- package/dist/runtime/openapi/generate-openapi.js +300 -0
- package/dist/runtime/openapi/generate-openapi.js.map +1 -0
- package/dist/runtime/openapi/index.d.ts +16 -0
- package/dist/runtime/openapi/index.d.ts.map +1 -0
- package/dist/runtime/openapi/index.js +16 -0
- package/dist/runtime/openapi/index.js.map +1 -0
- package/dist/selfimprove/scenarios/dhq-replay-find/golden.json +32 -0
- package/dist/selfimprove/scenarios/dhq-replay-find/scenario.json +18 -0
- package/dist/setup/config-json-merge.d.ts.map +1 -1
- package/dist/setup/config-json-merge.js +14 -0
- package/dist/setup/config-json-merge.js.map +1 -1
- package/dist/setup/index.d.ts +23 -11
- package/dist/setup/index.d.ts.map +1 -1
- package/dist/setup/index.js +25 -12
- package/dist/setup/index.js.map +1 -1
- package/dist/setup/sections/llm.d.ts +28 -1
- package/dist/setup/sections/llm.d.ts.map +1 -1
- package/dist/setup/sections/llm.js +27 -6
- package/dist/setup/sections/llm.js.map +1 -1
- package/dist/setup/sections/models-roles.d.ts +40 -0
- package/dist/setup/sections/models-roles.d.ts.map +1 -0
- package/dist/setup/sections/models-roles.js +219 -0
- package/dist/setup/sections/models-roles.js.map +1 -0
- package/dist/setup/wizard.d.ts +19 -1
- package/dist/setup/wizard.d.ts.map +1 -1
- package/dist/setup/wizard.js.map +1 -1
- package/dist/store/schedule-schema.d.ts +195 -0
- package/dist/store/schedule-schema.d.ts.map +1 -0
- package/dist/store/schedule-schema.js +84 -0
- package/dist/store/schedule-schema.js.map +1 -0
- package/dist/store/schedule-store.d.ts +144 -0
- package/dist/store/schedule-store.d.ts.map +1 -0
- package/dist/store/schedule-store.js +162 -0
- package/dist/store/schedule-store.js.map +1 -0
- package/dist/store/schema/attachments.d.ts +1 -1
- package/dist/store/schema/cleo-global/index.d.ts +3 -0
- package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/index.js +5 -0
- package/dist/store/schema/cleo-global/index.js.map +1 -1
- package/dist/store/schema/cleo-global/models-catalog.d.ts +359 -0
- package/dist/store/schema/cleo-global/models-catalog.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/models-catalog.js +114 -0
- package/dist/store/schema/cleo-global/models-catalog.js.map +1 -0
- package/dist/store/schema/cleo-global/providers.d.ts +279 -0
- package/dist/store/schema/cleo-global/providers.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/providers.js +94 -0
- package/dist/store/schema/cleo-global/providers.js.map +1 -0
- package/dist/store/schema/cleo-global/services.d.ts +493 -0
- package/dist/store/schema/cleo-global/services.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/services.js +200 -0
- package/dist/store/schema/cleo-global/services.js.map +1 -0
- package/dist/store/schema/cleo-project/docs.d.ts +1 -1
- package/dist/store/schema/cleo-project/provenance-rest.d.ts +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +2 -2
- package/dist/store/schema/memory-schema.d.ts +182 -2
- package/dist/store/schema/memory-schema.d.ts.map +1 -1
- package/dist/store/schema/memory-schema.js +111 -2
- package/dist/store/schema/memory-schema.js.map +1 -1
- package/dist/store/schema/provenance/releases.d.ts +1 -1
- package/dist/store/service-connections-accessor.d.ts +313 -0
- package/dist/store/service-connections-accessor.d.ts.map +1 -0
- package/dist/store/service-connections-accessor.js +464 -0
- package/dist/store/service-connections-accessor.js.map +1 -0
- package/dist/store/service-host-matcher.d.ts +70 -0
- package/dist/store/service-host-matcher.d.ts.map +1 -0
- package/dist/store/service-host-matcher.js +127 -0
- package/dist/store/service-host-matcher.js.map +1 -0
- package/dist/store/service-injection.d.ts +152 -0
- package/dist/store/service-injection.d.ts.map +1 -0
- package/dist/store/service-injection.js +225 -0
- package/dist/store/service-injection.js.map +1 -0
- package/dist/store/service-oauth.d.ts +287 -0
- package/dist/store/service-oauth.d.ts.map +1 -0
- package/dist/store/service-oauth.js +524 -0
- package/dist/store/service-oauth.js.map +1 -0
- package/dist/store/service-trust-gate.d.ts +164 -0
- package/dist/store/service-trust-gate.d.ts.map +1 -0
- package/dist/store/service-trust-gate.js +122 -0
- package/dist/store/service-trust-gate.js.map +1 -0
- package/dist/store/validation-schemas.d.ts +4 -4
- package/dist/tasks/agent-lifecycle-lane.d.ts +175 -0
- package/dist/tasks/agent-lifecycle-lane.d.ts.map +1 -0
- package/dist/tasks/agent-lifecycle-lane.js +176 -0
- package/dist/tasks/agent-lifecycle-lane.js.map +1 -0
- package/dist/tasks/complete.d.ts +17 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +53 -10
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/depends-waiver-audit.d.ts +52 -0
- package/dist/tasks/depends-waiver-audit.d.ts.map +1 -0
- package/dist/tasks/depends-waiver-audit.js +36 -0
- package/dist/tasks/depends-waiver-audit.js.map +1 -0
- package/dist/tasks/engine-wrap.d.ts +36 -2
- package/dist/tasks/engine-wrap.d.ts.map +1 -1
- package/dist/tasks/engine-wrap.js +44 -2
- package/dist/tasks/engine-wrap.js.map +1 -1
- package/dist/tasks/index.d.ts +1 -0
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/index.js +1 -0
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/ops.d.ts +3 -0
- package/dist/tasks/ops.d.ts.map +1 -1
- package/dist/tasks/task-ops.d.ts +1 -1
- package/dist/tasks/task-ops.d.ts.map +1 -1
- package/dist/tasks/task-ops.js +3 -1
- package/dist/tasks/task-ops.js.map +1 -1
- package/dist/tasks/task-reparent.d.ts +90 -0
- package/dist/tasks/task-reparent.d.ts.map +1 -1
- package/dist/tasks/task-reparent.js +171 -0
- package/dist/tasks/task-reparent.js.map +1 -1
- package/dist/tools/builtin-agent-tools.d.ts.map +1 -1
- package/dist/tools/builtin-agent-tools.js +41 -0
- package/dist/tools/builtin-agent-tools.js.map +1 -1
- package/dist/tools/exec-code-agent-tool.d.ts +179 -0
- package/dist/tools/exec-code-agent-tool.d.ts.map +1 -0
- package/dist/tools/exec-code-agent-tool.js +239 -0
- package/dist/tools/exec-code-agent-tool.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp-agent-tool.d.ts +189 -0
- package/dist/tools/mcp-agent-tool.d.ts.map +1 -0
- package/dist/tools/mcp-agent-tool.js +243 -0
- package/dist/tools/mcp-agent-tool.js.map +1 -0
- package/dist/tools/media-agent-tools.d.ts +105 -0
- package/dist/tools/media-agent-tools.d.ts.map +1 -0
- package/dist/tools/media-agent-tools.js +255 -0
- package/dist/tools/media-agent-tools.js.map +1 -0
- package/dist/tools/memory-agent-tools.d.ts +99 -0
- package/dist/tools/memory-agent-tools.d.ts.map +1 -0
- package/dist/tools/memory-agent-tools.js +190 -0
- package/dist/tools/memory-agent-tools.js.map +1 -0
- package/dist/tools/schedule-agent-tools.d.ts +151 -0
- package/dist/tools/schedule-agent-tools.d.ts.map +1 -0
- package/dist/tools/schedule-agent-tools.js +238 -0
- package/dist/tools/schedule-agent-tools.js.map +1 -0
- package/dist/tools/skill-agent-tool.d.ts +108 -0
- package/dist/tools/skill-agent-tool.d.ts.map +1 -0
- package/dist/tools/skill-agent-tool.js +135 -0
- package/dist/tools/skill-agent-tool.js.map +1 -0
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +17 -1
- package/dist/validation/engine-ops.js.map +1 -1
- package/migrations/drizzle-brain/20260610000001_t10405-bitemporal-network-columns/migration.sql +71 -0
- package/migrations/drizzle-cleo-global/20260609000000_t11937-service-vault/migration.sql +93 -0
- package/migrations/drizzle-cleo-global/20260609010000_t11733-models-catalog/migration.sql +65 -0
- package/migrations/drizzle-cleo-global/20260609020000_t11703-providers/migration.sql +52 -0
- package/migrations/drizzle-cleo-global/20260610000000_t11962-schedules/migration.sql +48 -0
- package/migrations/drizzle-cleo-project/20260610000000_t11962-schedules/migration.sql +48 -0
- package/package.json +23 -13
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service-vault accessor — store-level CRUD + policy-before-decrypt egress.
|
|
3
|
+
*
|
|
4
|
+
* EP-UNIVERSAL-SERVICE-VAULT (epic T11765 · saga SG-VAULT-CORE T10409 · M2 W1a ·
|
|
5
|
+
* task T11937 · AC3). The store layer for the universal SERVICE-credential vault
|
|
6
|
+
* (`service_connections` / `service_configs` / `agent_service_grants`).
|
|
7
|
+
*
|
|
8
|
+
* ## DB Open Guard (Gate 3 — strict)
|
|
9
|
+
*
|
|
10
|
+
* EVERY open goes through {@link openDualScopeDb}`('global')` (or its path-aware
|
|
11
|
+
* sibling {@link openDualScopeDbAtPath} for an injected test DB) — there is ZERO
|
|
12
|
+
* raw `new DatabaseSync(`. The typed Drizzle handle drives all CRUD; the accessor
|
|
13
|
+
* never constructs a native handle itself.
|
|
14
|
+
*
|
|
15
|
+
* ## Crypto reuse (DRY — no new crypto · T11710)
|
|
16
|
+
*
|
|
17
|
+
* `credentials_enc` holds the {@link encryptGlobal} ciphertext of the
|
|
18
|
+
* `{access_token, refresh_token}` JSON, keyed `id = service:${provider}:${label}`.
|
|
19
|
+
* The accessor calls {@link encryptGlobal}/{@link decryptGlobal} from
|
|
20
|
+
* `crypto/credentials.ts` — it adds no crypto of its own. The crypto functions are
|
|
21
|
+
* injectable ({@link ServiceVaultDeps}) so a test can spy on `decryptGlobal` and
|
|
22
|
+
* PROVE it is never invoked on a denied access (policy-before-decrypt, AC4).
|
|
23
|
+
*
|
|
24
|
+
* ## Policy-before-decrypt egress (AC4)
|
|
25
|
+
*
|
|
26
|
+
* {@link resolveSealedConnection} evaluates the {@link evaluateServiceAccess}
|
|
27
|
+
* trust gate FIRST (a pure decision from the agent's grant rows). It calls
|
|
28
|
+
* `decryptGlobal` ONLY when the gate returns `allowed: true`. A denied agent
|
|
29
|
+
* returns `null` BEFORE the decrypt call — the decrypt closure never runs. On
|
|
30
|
+
* allow, the plaintext is not surfaced inline: it is wrapped in a
|
|
31
|
+
* {@link makeSealedCredential} handle whose `resolveToken` thunk performs the
|
|
32
|
+
* decrypt at the wire (the same egress the LLM credential pool uses).
|
|
33
|
+
*
|
|
34
|
+
* ## OAuth seam (T11939)
|
|
35
|
+
*
|
|
36
|
+
* The OAuth build/exchange/refresh dance is the FOLLOW-UP (T11939). This accessor
|
|
37
|
+
* leaves the clean seam: {@link connectService} accepts an already-obtained token
|
|
38
|
+
* blob and writes its `encryptGlobal` ciphertext into `credentials_enc`; the OAuth
|
|
39
|
+
* flow simply calls `connectService` (or `updateConnectionCredentials`) with the
|
|
40
|
+
* tokens it negotiates. No OAuth logic lives here.
|
|
41
|
+
*
|
|
42
|
+
* @module store/service-connections-accessor
|
|
43
|
+
* @task T11937
|
|
44
|
+
* @epic T11765
|
|
45
|
+
* @saga T10409
|
|
46
|
+
* @see ./schema/cleo-global/services.ts — the three tables
|
|
47
|
+
* @see ./service-trust-gate.ts — the policy-before-decrypt decision
|
|
48
|
+
* @see ../crypto/credentials.ts — `encryptGlobal` / `decryptGlobal` (reused, not re-implemented)
|
|
49
|
+
* @see ../llm/sealed-credential.ts — `makeSealedCredential` (the shared egress handle)
|
|
50
|
+
*/
|
|
51
|
+
import { and, eq } from 'drizzle-orm';
|
|
52
|
+
import { decryptGlobal, encryptGlobal } from '../crypto/credentials.js';
|
|
53
|
+
import { makeSealedCredential, tokenPreview } from '../llm/sealed-credential.js';
|
|
54
|
+
import { openDualScopeDb, openDualScopeDbAtPath } from './dual-scope-db.js';
|
|
55
|
+
import { agentServiceGrants, serviceConnections, } from './schema/cleo-global/services.js';
|
|
56
|
+
import { evaluateServiceAccess, parseSessionPolicy, } from './service-trust-gate.js';
|
|
57
|
+
/** The `encryptGlobal`/`decryptGlobal` id for a connection's token blob. */
|
|
58
|
+
function credentialId(provider, label) {
|
|
59
|
+
return `service:${provider}:${label}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Open the global service-vault handle at an EXPLICIT path (test seam).
|
|
63
|
+
*
|
|
64
|
+
* Production callers MUST use {@link openDualScopeDb}`('global')` (resolved
|
|
65
|
+
* canonical path). This path-aware variant exists so tests open a temp-dir
|
|
66
|
+
* `cleo.db` — never `.cleo/*.db`. Returns the typed global Drizzle handle.
|
|
67
|
+
*
|
|
68
|
+
* @param dbPath - Absolute path to the temp `cleo.db`.
|
|
69
|
+
* @returns The typed {@link CleoGlobalDb} handle.
|
|
70
|
+
* @task T11937
|
|
71
|
+
*/
|
|
72
|
+
export async function openServiceVaultAtPath(dbPath) {
|
|
73
|
+
const handle = await openDualScopeDbAtPath('global', dbPath);
|
|
74
|
+
return handle.db;
|
|
75
|
+
}
|
|
76
|
+
/** Resolve the global Drizzle handle — injected, else canonical open. */
|
|
77
|
+
async function resolveDb(deps) {
|
|
78
|
+
if (deps?.db !== undefined)
|
|
79
|
+
return deps.db;
|
|
80
|
+
const handle = await openDualScopeDb('global');
|
|
81
|
+
return handle.db;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* CONNECT a service: encrypt the token blob and upsert the connection row.
|
|
85
|
+
*
|
|
86
|
+
* The token blob is JSON-serialized and {@link encryptGlobal}-encrypted under
|
|
87
|
+
* `id = service:${provider}:${label}` — only the ciphertext is written. On a
|
|
88
|
+
* repeat `connect` for the same `(provider, label)` the row's credentials/scopes/
|
|
89
|
+
* metadata/expiry are REFRESHED in place and `status` is reset to `active` (an
|
|
90
|
+
* expired/revoked connection is re-activated by re-connecting).
|
|
91
|
+
*
|
|
92
|
+
* @returns The connection id.
|
|
93
|
+
* @task T11937
|
|
94
|
+
*/
|
|
95
|
+
export async function connectService(params, deps) {
|
|
96
|
+
const db = await resolveDb(deps);
|
|
97
|
+
const encrypt = deps?.encrypt ?? encryptGlobal;
|
|
98
|
+
const id = credentialId(params.provider, params.label);
|
|
99
|
+
const credentialsEnc = await encrypt(JSON.stringify(params.tokens), id);
|
|
100
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
101
|
+
const scopesJson = JSON.stringify(params.scopes ?? []);
|
|
102
|
+
const metadataJson = JSON.stringify(params.metadata ?? {});
|
|
103
|
+
const existing = await db
|
|
104
|
+
.select({ id: serviceConnections.id })
|
|
105
|
+
.from(serviceConnections)
|
|
106
|
+
.where(and(eq(serviceConnections.provider, params.provider), eq(serviceConnections.label, params.label)))
|
|
107
|
+
.limit(1);
|
|
108
|
+
if (existing.length > 0 && existing[0] !== undefined) {
|
|
109
|
+
const connId = existing[0].id;
|
|
110
|
+
await db
|
|
111
|
+
.update(serviceConnections)
|
|
112
|
+
.set({
|
|
113
|
+
status: 'active',
|
|
114
|
+
credentialsEnc,
|
|
115
|
+
scopes: scopesJson,
|
|
116
|
+
expiresAt: params.expiresAt ?? null,
|
|
117
|
+
metadata: metadataJson,
|
|
118
|
+
updatedAt: now,
|
|
119
|
+
})
|
|
120
|
+
.where(eq(serviceConnections.id, connId));
|
|
121
|
+
return connId;
|
|
122
|
+
}
|
|
123
|
+
const inserted = await db
|
|
124
|
+
.insert(serviceConnections)
|
|
125
|
+
.values({
|
|
126
|
+
provider: params.provider,
|
|
127
|
+
label: params.label,
|
|
128
|
+
status: 'active',
|
|
129
|
+
credentialsEnc,
|
|
130
|
+
scopes: scopesJson,
|
|
131
|
+
expiresAt: params.expiresAt ?? null,
|
|
132
|
+
metadata: metadataJson,
|
|
133
|
+
})
|
|
134
|
+
.returning({ id: serviceConnections.id });
|
|
135
|
+
const row = inserted[0];
|
|
136
|
+
if (row === undefined) {
|
|
137
|
+
throw new Error('service connect: insert returned no id');
|
|
138
|
+
}
|
|
139
|
+
return row.id;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* UPDATE a connection's encrypted token blob + expiry in place (OAuth refresh
|
|
143
|
+
* persistence seam — T11939).
|
|
144
|
+
*
|
|
145
|
+
* The self-heal path ({@link import('./service-oauth.js').selfHealConnection})
|
|
146
|
+
* calls this after a refresh: the new `{accessToken, refreshToken}` blob is
|
|
147
|
+
* {@link encryptGlobal}-encrypted under the SAME `id = service:${provider}:${label}`
|
|
148
|
+
* and written back, with `expires_at` bumped and `status` kept `active`. Only the
|
|
149
|
+
* ciphertext is persisted — exactly like {@link connectService}.
|
|
150
|
+
*
|
|
151
|
+
* @returns `true` if a row was updated, `false` when no such `(provider, label)`.
|
|
152
|
+
* @task T11939
|
|
153
|
+
*/
|
|
154
|
+
export async function updateConnectionTokens(params, deps) {
|
|
155
|
+
const db = await resolveDb(deps);
|
|
156
|
+
const encrypt = deps?.encrypt ?? encryptGlobal;
|
|
157
|
+
const id = credentialId(params.provider, params.label);
|
|
158
|
+
const credentialsEnc = await encrypt(JSON.stringify(params.tokens), id);
|
|
159
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
160
|
+
const updated = await db
|
|
161
|
+
.update(serviceConnections)
|
|
162
|
+
.set({
|
|
163
|
+
credentialsEnc,
|
|
164
|
+
...(params.expiresAt !== undefined ? { expiresAt: params.expiresAt } : {}),
|
|
165
|
+
updatedAt: now,
|
|
166
|
+
})
|
|
167
|
+
.where(and(eq(serviceConnections.provider, params.provider), eq(serviceConnections.label, params.label)))
|
|
168
|
+
.returning({ id: serviceConnections.id });
|
|
169
|
+
return updated.length > 0;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* RESOLVE a connection's DECRYPTED token blob — **policy-before-decrypt** (T11939).
|
|
173
|
+
*
|
|
174
|
+
* The self-heal seam: the OAuth flow needs the REFRESH token (inside the encrypted
|
|
175
|
+
* blob) plus `expires_at` to decide whether to refresh. Like
|
|
176
|
+
* {@link resolveSealedConnection}, the trust gate runs FIRST and `decryptGlobal`
|
|
177
|
+
* is invoked ONLY on allow — a denied agent gets `null` with NO decrypt. Unlike
|
|
178
|
+
* the sealed resolve, this returns the plaintext blob inline (the caller is the
|
|
179
|
+
* refresh machinery, which re-encrypts immediately) so it MUST NOT cross a
|
|
180
|
+
* logging/serialization boundary.
|
|
181
|
+
*
|
|
182
|
+
* @returns The decrypted blob + expiry on allow; `null` when denied / missing /
|
|
183
|
+
* not `active` / no stored credential.
|
|
184
|
+
* @task T11939
|
|
185
|
+
*/
|
|
186
|
+
export async function loadDecryptedTokenBlob(params, deps) {
|
|
187
|
+
const db = await resolveDb(deps);
|
|
188
|
+
const decrypt = deps?.decrypt ?? decryptGlobal;
|
|
189
|
+
const rows = await db
|
|
190
|
+
.select()
|
|
191
|
+
.from(serviceConnections)
|
|
192
|
+
.where(and(eq(serviceConnections.provider, params.provider), eq(serviceConnections.label, params.label)))
|
|
193
|
+
.limit(1);
|
|
194
|
+
const conn = rows[0];
|
|
195
|
+
if (conn === undefined || conn.status !== 'active' || conn.credentialsEnc === null) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
// POLICY BEFORE DECRYPT — no crypto has run yet.
|
|
199
|
+
const grants = await loadAgentGrants(db, params.agentId);
|
|
200
|
+
const decision = evaluateServiceAccess(grants, {
|
|
201
|
+
agentId: params.agentId,
|
|
202
|
+
serviceConnectionId: conn.id,
|
|
203
|
+
approved: params.approved,
|
|
204
|
+
});
|
|
205
|
+
if (!decision.allowed) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const id = credentialId(params.provider, params.label);
|
|
209
|
+
const plaintext = await decrypt(conn.credentialsEnc, id);
|
|
210
|
+
const blob = JSON.parse(plaintext);
|
|
211
|
+
return { id: conn.id, blob, expiresAt: conn.expiresAt };
|
|
212
|
+
}
|
|
213
|
+
/** Map a raw connection row to a non-secret {@link ServiceConnectionView}. */
|
|
214
|
+
function toView(row) {
|
|
215
|
+
let scopes = [];
|
|
216
|
+
let metadata = {};
|
|
217
|
+
try {
|
|
218
|
+
const parsed = JSON.parse(row.scopes);
|
|
219
|
+
if (Array.isArray(parsed))
|
|
220
|
+
scopes = parsed.filter((s) => typeof s === 'string');
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// malformed scopes JSON → empty list (non-secret display only)
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const parsed = JSON.parse(row.metadata);
|
|
227
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
228
|
+
metadata = parsed;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// malformed metadata JSON → empty object
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
id: row.id,
|
|
236
|
+
provider: row.provider,
|
|
237
|
+
label: row.label,
|
|
238
|
+
status: row.status,
|
|
239
|
+
scopes,
|
|
240
|
+
expiresAt: row.expiresAt,
|
|
241
|
+
metadata,
|
|
242
|
+
connectedAt: row.connectedAt,
|
|
243
|
+
updatedAt: row.updatedAt,
|
|
244
|
+
hasCredentials: row.credentialsEnc !== null && row.credentialsEnc !== '',
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* GET one connection as a non-secret view (NEVER decrypts the token).
|
|
249
|
+
*
|
|
250
|
+
* @returns The view, or `null` when no such `(provider, label)` exists.
|
|
251
|
+
* @task T11937
|
|
252
|
+
*/
|
|
253
|
+
export async function getConnection(provider, label, deps) {
|
|
254
|
+
const db = await resolveDb(deps);
|
|
255
|
+
const rows = await db
|
|
256
|
+
.select()
|
|
257
|
+
.from(serviceConnections)
|
|
258
|
+
.where(and(eq(serviceConnections.provider, provider), eq(serviceConnections.label, label)))
|
|
259
|
+
.limit(1);
|
|
260
|
+
const row = rows[0];
|
|
261
|
+
return row === undefined ? null : toView(row);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* LIST connections as non-secret views (NEVER decrypts), optionally by provider.
|
|
265
|
+
*
|
|
266
|
+
* @param provider - When set, restrict to one provider; otherwise all.
|
|
267
|
+
* @task T11937
|
|
268
|
+
*/
|
|
269
|
+
export async function listConnections(provider, deps) {
|
|
270
|
+
const db = await resolveDb(deps);
|
|
271
|
+
const rows = provider === undefined
|
|
272
|
+
? await db.select().from(serviceConnections)
|
|
273
|
+
: await db.select().from(serviceConnections).where(eq(serviceConnections.provider, provider));
|
|
274
|
+
return rows.map(toView);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* LIST every agent grant as a NON-SECRET {@link AgentGrantView}, joined to its
|
|
278
|
+
* connection's `provider`/`label` for display. NEVER decrypts and never carries
|
|
279
|
+
* a token — the dashboard read path (T11943).
|
|
280
|
+
*
|
|
281
|
+
* The join is performed in-memory (one `agent_service_grants` scan + one
|
|
282
|
+
* `service_connections` scan, both already redacted) so the accessor stays a
|
|
283
|
+
* pure read with no second round-trip per grant. A grant whose connection was
|
|
284
|
+
* deleted out-of-band resolves `provider`/`label` to `null` (defensive — the
|
|
285
|
+
* cascade should prevent this, but the view must not throw).
|
|
286
|
+
*
|
|
287
|
+
* @param agentId - When set, restrict to one agent's grants; otherwise all.
|
|
288
|
+
* @task T11943
|
|
289
|
+
*/
|
|
290
|
+
export async function listAllGrants(agentId, deps) {
|
|
291
|
+
const db = await resolveDb(deps);
|
|
292
|
+
const grantRows = agentId === undefined
|
|
293
|
+
? await db.select().from(agentServiceGrants)
|
|
294
|
+
: await db.select().from(agentServiceGrants).where(eq(agentServiceGrants.agentId, agentId));
|
|
295
|
+
// Build a connection-id → identity map once (redacted views, no token).
|
|
296
|
+
const connRows = await db.select().from(serviceConnections);
|
|
297
|
+
const identityById = new Map();
|
|
298
|
+
for (const c of connRows)
|
|
299
|
+
identityById.set(c.id, { provider: c.provider, label: c.label });
|
|
300
|
+
return grantRows.map((g) => {
|
|
301
|
+
const identity = identityById.get(g.serviceConnectionId) ?? null;
|
|
302
|
+
const policy = parseSessionPolicy(g.sessionPolicy);
|
|
303
|
+
return {
|
|
304
|
+
agentId: g.agentId,
|
|
305
|
+
serviceConnectionId: g.serviceConnectionId,
|
|
306
|
+
provider: identity?.provider ?? null,
|
|
307
|
+
label: identity?.label ?? null,
|
|
308
|
+
mode: policy.mode,
|
|
309
|
+
manualApproval: policy.manualApproval ?? false,
|
|
310
|
+
createdAt: g.createdAt,
|
|
311
|
+
updatedAt: g.updatedAt,
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* REVOKE a connection: flip `status` to `revoked` and CLEAR the credential blob.
|
|
317
|
+
*
|
|
318
|
+
* Clearing `credentials_enc` makes the secret unrecoverable (the ciphertext is
|
|
319
|
+
* gone) — a revoke is permanent until a fresh `connect`. The row is kept (not
|
|
320
|
+
* deleted) so grants/audit referencing it remain coherent.
|
|
321
|
+
*
|
|
322
|
+
* @returns `true` if a row was revoked, `false` if no such connection.
|
|
323
|
+
* @task T11937
|
|
324
|
+
*/
|
|
325
|
+
export async function revokeConnection(provider, label, deps) {
|
|
326
|
+
const db = await resolveDb(deps);
|
|
327
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
328
|
+
const updated = await db
|
|
329
|
+
.update(serviceConnections)
|
|
330
|
+
.set({ status: 'revoked', credentialsEnc: null, updatedAt: now })
|
|
331
|
+
.where(and(eq(serviceConnections.provider, provider), eq(serviceConnections.label, label)))
|
|
332
|
+
.returning({ id: serviceConnections.id });
|
|
333
|
+
return updated.length > 0;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* DELETE a connection and CASCADE its agent grants (the hard `service revoke`).
|
|
337
|
+
*
|
|
338
|
+
* Unlike {@link revokeConnection} (a soft status flip that keeps the row), this
|
|
339
|
+
* REMOVES the `service_connections` row entirely and first deletes every
|
|
340
|
+
* `agent_service_grants` row that references it. The cascade is performed
|
|
341
|
+
* EXPLICITLY in application code — the in-file FK on `service_connection_id` is
|
|
342
|
+
* declared without `ON DELETE CASCADE`, and `foreign_keys` is not assumed ON —
|
|
343
|
+
* so grants are deleted FIRST, then the connection, leaving no dangling grant.
|
|
344
|
+
*
|
|
345
|
+
* @returns A {@link DeleteConnectionResult} reporting the cascade outcome.
|
|
346
|
+
* @task T11941
|
|
347
|
+
*/
|
|
348
|
+
export async function deleteConnectionCascade(provider, label, deps) {
|
|
349
|
+
const db = await resolveDb(deps);
|
|
350
|
+
const rows = await db
|
|
351
|
+
.select({ id: serviceConnections.id })
|
|
352
|
+
.from(serviceConnections)
|
|
353
|
+
.where(and(eq(serviceConnections.provider, provider), eq(serviceConnections.label, label)))
|
|
354
|
+
.limit(1);
|
|
355
|
+
const row = rows[0];
|
|
356
|
+
if (row === undefined) {
|
|
357
|
+
return { deleted: false, connectionId: null, grantsRemoved: 0 };
|
|
358
|
+
}
|
|
359
|
+
const connectionId = row.id;
|
|
360
|
+
// Cascade grants FIRST (no ON DELETE CASCADE on the FK), then the connection.
|
|
361
|
+
const removedGrants = await db
|
|
362
|
+
.delete(agentServiceGrants)
|
|
363
|
+
.where(eq(agentServiceGrants.serviceConnectionId, connectionId))
|
|
364
|
+
.returning({ agentId: agentServiceGrants.agentId });
|
|
365
|
+
await db.delete(serviceConnections).where(eq(serviceConnections.id, connectionId));
|
|
366
|
+
return { deleted: true, connectionId, grantsRemoved: removedGrants.length };
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* GRANT an agent access to a connection with a session policy.
|
|
370
|
+
*
|
|
371
|
+
* @param agentId - The agent to grant.
|
|
372
|
+
* @param serviceConnectionId - The connection id (from {@link connectService}).
|
|
373
|
+
* @param policy - The {@link SessionPolicy}; defaults to a bare allow.
|
|
374
|
+
* @task T11937
|
|
375
|
+
*/
|
|
376
|
+
export async function grantAgentAccess(agentId, serviceConnectionId, policy = { mode: 'allow' }, deps) {
|
|
377
|
+
const db = await resolveDb(deps);
|
|
378
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
379
|
+
const policyJson = JSON.stringify(policy);
|
|
380
|
+
const existing = await db
|
|
381
|
+
.select({ agentId: agentServiceGrants.agentId })
|
|
382
|
+
.from(agentServiceGrants)
|
|
383
|
+
.where(and(eq(agentServiceGrants.agentId, agentId), eq(agentServiceGrants.serviceConnectionId, serviceConnectionId)))
|
|
384
|
+
.limit(1);
|
|
385
|
+
if (existing.length > 0) {
|
|
386
|
+
await db
|
|
387
|
+
.update(agentServiceGrants)
|
|
388
|
+
.set({ sessionPolicy: policyJson, updatedAt: now })
|
|
389
|
+
.where(and(eq(agentServiceGrants.agentId, agentId), eq(agentServiceGrants.serviceConnectionId, serviceConnectionId)));
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
await db
|
|
393
|
+
.insert(agentServiceGrants)
|
|
394
|
+
.values({ agentId, serviceConnectionId, sessionPolicy: policyJson });
|
|
395
|
+
}
|
|
396
|
+
/** Load an agent's grants as the gate-shaped {@link ServiceGrant} projection. */
|
|
397
|
+
async function loadAgentGrants(db, agentId) {
|
|
398
|
+
const rows = await db
|
|
399
|
+
.select()
|
|
400
|
+
.from(agentServiceGrants)
|
|
401
|
+
.where(eq(agentServiceGrants.agentId, agentId));
|
|
402
|
+
return rows.map((r) => ({
|
|
403
|
+
agentId: r.agentId,
|
|
404
|
+
serviceConnectionId: r.serviceConnectionId,
|
|
405
|
+
sessionPolicy: parseSessionPolicy(r.sessionPolicy),
|
|
406
|
+
}));
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* RESOLVE a connection to a sealed credential — **policy-before-decrypt** egress.
|
|
410
|
+
*
|
|
411
|
+
* The trust gate runs FIRST (a pure {@link evaluateServiceAccess} decision over
|
|
412
|
+
* the agent's grants). `decryptGlobal` is invoked ONLY when the gate returns
|
|
413
|
+
* `allowed: true` — and even then NOT inline: the plaintext is materialized lazily
|
|
414
|
+
* inside the {@link makeSealedCredential} `resolveToken` thunk at the wire. A
|
|
415
|
+
* denied agent returns `null` BEFORE the decrypt closure is ever built or run, so
|
|
416
|
+
* a spy on `decryptGlobal` records ZERO calls on a deny (AC4 proof).
|
|
417
|
+
*
|
|
418
|
+
* @returns A {@link SealedCredential} on allow; `null` when denied or when the
|
|
419
|
+
* connection is missing / not `active` / has no stored credential.
|
|
420
|
+
* @task T11937
|
|
421
|
+
*/
|
|
422
|
+
export async function resolveSealedConnection(params, deps) {
|
|
423
|
+
const db = await resolveDb(deps);
|
|
424
|
+
const decrypt = deps?.decrypt ?? decryptGlobal;
|
|
425
|
+
// 1. Load the connection (non-secret) — needed for the gate's connection id.
|
|
426
|
+
const rows = await db
|
|
427
|
+
.select()
|
|
428
|
+
.from(serviceConnections)
|
|
429
|
+
.where(and(eq(serviceConnections.provider, params.provider), eq(serviceConnections.label, params.label)))
|
|
430
|
+
.limit(1);
|
|
431
|
+
const conn = rows[0];
|
|
432
|
+
if (conn === undefined || conn.status !== 'active' || conn.credentialsEnc === null) {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
// 2. POLICY BEFORE DECRYPT — evaluate the trust gate. No crypto has run yet.
|
|
436
|
+
const grants = await loadAgentGrants(db, params.agentId);
|
|
437
|
+
const decision = evaluateServiceAccess(grants, {
|
|
438
|
+
agentId: params.agentId,
|
|
439
|
+
serviceConnectionId: conn.id,
|
|
440
|
+
approved: params.approved,
|
|
441
|
+
});
|
|
442
|
+
if (!decision.allowed) {
|
|
443
|
+
// Denied — return BEFORE building/running the decrypt thunk. `decrypt`
|
|
444
|
+
// (the spied `decryptGlobal`) is never called on this path (AC4).
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
// 3. Allowed — wrap in a sealed handle whose resolveToken decrypts AT THE WIRE.
|
|
448
|
+
const ciphertext = conn.credentialsEnc;
|
|
449
|
+
const id = credentialId(params.provider, params.label);
|
|
450
|
+
return makeSealedCredential({
|
|
451
|
+
provider: params.provider,
|
|
452
|
+
account: params.label,
|
|
453
|
+
// Non-secret preview: we have not decrypted, so name the credential by id.
|
|
454
|
+
tokenPreview: tokenPreview('', 'oauth'),
|
|
455
|
+
resolveToken: async () => {
|
|
456
|
+
// The SOLE decrypt point — runs only when the wire calls fetch(). Returns
|
|
457
|
+
// the access token (the wire-bound bearer); refresh stays in the blob.
|
|
458
|
+
const plaintext = await decrypt(ciphertext, id);
|
|
459
|
+
const blob = JSON.parse(plaintext);
|
|
460
|
+
return blob.accessToken;
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
//# sourceMappingURL=service-connections-accessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-connections-accessor.js","sourceRoot":"","sources":["../../src/store/service-connections-accessor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service host/path → provider matcher (T11940 · M2-W3 · AC1).
|
|
3
|
+
*
|
|
4
|
+
* EP-UNIVERSAL-SERVICE-VAULT (epic T11765 · saga SG-VAULT-CORE T10409). The first
|
|
5
|
+
* half of the injection-at-tool-boundary seam: given the host (and optional path)
|
|
6
|
+
* of an outbound request a harness tool is about to make, resolve which
|
|
7
|
+
* {@link ServiceProviderDef} (and therefore which `service_connections` provider)
|
|
8
|
+
* the request's host belongs to, plus the matching {@link ServiceHostRule} that
|
|
9
|
+
* declares HOW the credential is injected (the {@link HostAuthStrategy}).
|
|
10
|
+
*
|
|
11
|
+
* Pure, side-effect-free, decrypt-free: it consults ONLY the declarative
|
|
12
|
+
* {@link SERVICE_PROVIDERS} registry (frozen DATA in `@cleocode/contracts`). It
|
|
13
|
+
* never opens a DB, never decrypts, never touches the network — so it is NOT a DB
|
|
14
|
+
* chokepoint concern (Gate 3) and carries no credential material.
|
|
15
|
+
*
|
|
16
|
+
* ## Matching model (mirrors onecli `apps.rs::match_host`)
|
|
17
|
+
*
|
|
18
|
+
* `host` matches EXACTLY against `ServiceHostRule.host`, with one well-defined
|
|
19
|
+
* suffix case: a rule host beginning with `.` (or a registry host that is a bare
|
|
20
|
+
* apex like `amazonaws.com`) matches any sub-domain suffix — used for wildcard
|
|
21
|
+
* families like AWS. `pathPrefix`, when present on a rule, further narrows the
|
|
22
|
+
* match to requests whose path starts with it (e.g. the legacy
|
|
23
|
+
* `www.googleapis.com/gmail/` endpoints). When multiple rules match, the MOST
|
|
24
|
+
* SPECIFIC wins: a `pathPrefix` rule beats a host-only rule, and a longer
|
|
25
|
+
* `pathPrefix` beats a shorter one.
|
|
26
|
+
*
|
|
27
|
+
* @module store/service-host-matcher
|
|
28
|
+
* @task T11940
|
|
29
|
+
* @epic T11765
|
|
30
|
+
* @saga T10409
|
|
31
|
+
* @see @cleocode/contracts/vault/service-provider — SERVICE_PROVIDERS + ServiceHostRule
|
|
32
|
+
* @see ./service-injection.ts — the injector that consumes a match to mutate a request
|
|
33
|
+
*/
|
|
34
|
+
import { type HostAuthStrategy, type ServiceHostRule, type ServiceProviderDef } from '@cleocode/contracts';
|
|
35
|
+
/** The result of resolving an outbound request's host/path to a service provider. */
|
|
36
|
+
export interface ServiceHostMatch {
|
|
37
|
+
/** The matched provider definition. */
|
|
38
|
+
readonly provider: ServiceProviderDef;
|
|
39
|
+
/** The specific host rule that matched (declares the injection strategy). */
|
|
40
|
+
readonly rule: ServiceHostRule;
|
|
41
|
+
/** Convenience: the injection strategy from {@link rule}. */
|
|
42
|
+
readonly strategy: HostAuthStrategy;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve an outbound request's host (+ optional path) to the matching service
|
|
46
|
+
* provider + host rule, or `null` when no provider claims the host (T11940 AC1).
|
|
47
|
+
*
|
|
48
|
+
* When several rules match (e.g. a host-only rule and a `pathPrefix` rule on the
|
|
49
|
+
* same host), the MOST SPECIFIC wins: a rule with a `pathPrefix` beats one without,
|
|
50
|
+
* and a longer `pathPrefix` beats a shorter one. Among equally-specific matches the
|
|
51
|
+
* first registry entry wins (stable iteration order of {@link SERVICE_PROVIDERS}).
|
|
52
|
+
*
|
|
53
|
+
* @param host - The request host (e.g. `api.github.com`; a `:port` / trailing dot
|
|
54
|
+
* is tolerated).
|
|
55
|
+
* @param path - The request path (defaults to `/`); narrows `pathPrefix` rules.
|
|
56
|
+
* @returns The {@link ServiceHostMatch}, or `null` when no provider matches.
|
|
57
|
+
* @task T11940
|
|
58
|
+
*/
|
|
59
|
+
export declare function matchServiceHost(host: string, path?: string): ServiceHostMatch | null;
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the matching provider for a full URL string (convenience over
|
|
62
|
+
* {@link matchServiceHost} that parses the URL's host + path).
|
|
63
|
+
*
|
|
64
|
+
* @param url - The absolute request URL (e.g. `https://api.github.com/user`).
|
|
65
|
+
* @returns The {@link ServiceHostMatch}, or `null` when the URL is unparseable or
|
|
66
|
+
* no provider matches.
|
|
67
|
+
* @task T11940
|
|
68
|
+
*/
|
|
69
|
+
export declare function matchServiceUrl(url: string): ServiceHostMatch | null;
|
|
70
|
+
//# sourceMappingURL=service-host-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-host-matcher.d.ts","sourceRoot":"","sources":["../../src/store/service-host-matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;CACrC;AAwCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,gBAAgB,GAAG,IAAI,CAmBlF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQpE"}
|