@desplega.ai/agent-swarm 1.149.1 → 1.151.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 +18 -3
- package/dist/{acp-adapter-vhkzfpjg.js → acp-adapter-ex8hzjfc.js} +5 -5
- package/dist/{actions-9d2694yk.js → actions-2bgpyhww.js} +39 -11
- package/dist/{app-fq2ggynt.js → app-1706zhr1.js} +7 -7
- package/dist/{artifact-gj9arwrr.js → artifact-td4q4dch.js} +1 -1
- package/dist/{assistant-edb6n9nn.js → assistant-bavke5p7.js} +44 -20
- package/dist/{azure-openai-responses-cqar64rc.js → azure-openai-responses-f38x2avq.js} +13 -13
- package/dist/{boot-reembed-msweabbp.js → boot-reembed-3cmrrmpa.js} +9 -9
- package/dist/{boot-reembed-q5wd3tha.js → boot-reembed-nafcmmmc.js} +14 -16
- package/dist/{boot-scrub-logs-3g1az933.js → boot-scrub-logs-cd6a2sq0.js} +5 -5
- package/dist/{claude-adapter-v3rnzsdc.js → claude-adapter-wfp2gzvz.js} +15 -16
- package/dist/{claude-managed-adapter-qvsmh6mv.js → claude-managed-adapter-dsmkcrjy.js} +3 -3
- package/dist/{claude-sdk-session-qxrpsna1.js → claude-sdk-session-bht9jjak.js} +15 -16
- package/dist/{cli-5m0qmvdp.js → cli-0qb1z6s2.js} +1 -1
- package/dist/{cli-9d8ntetj.js → cli-2658f6at.js} +1 -1
- package/dist/{cli-7evafqvy.js → cli-2tbvf1z1.js} +85 -69
- package/dist/{cli-k351hv5k.js → cli-3v9xhjcn.js} +24 -12
- package/dist/{cli-1ebpar1q.js → cli-4wppfkcm.js} +350 -20
- package/dist/{cli-4260r1tg.js → cli-5jd2z7av.js} +97 -84
- package/dist/{cli-cv7s5zdq.js → cli-5tpgq60f.js} +9865 -715
- package/dist/{cli-6skz3rk8.js → cli-7tgcstn2.js} +9 -4
- package/dist/{cli-01g3x1ca.js → cli-9004vfdf.js} +108 -56
- package/dist/{cli-1c94wvcw.js → cli-a1z3h107.js} +124 -99
- package/dist/{cli-9br8ypfv.js → cli-czjtgfys.js} +2 -2
- package/dist/{cli-5my3bjsd.js → cli-d3p82erb.js} +7 -7
- package/dist/{cli-e29gmdmw.js → cli-dv6cdjs2.js} +2 -1
- package/dist/{cli-wby1xnnb.js → cli-f1wky6zp.js} +1 -1
- package/dist/{cli-zvz62chv.js → cli-fm4ytsdk.js} +4 -4
- package/dist/{cli-tg8qj8ee.js → cli-frcta2w4.js} +6 -6
- package/dist/{cli-7xx10h0a.js → cli-g69fdc9g.js} +2 -2
- package/dist/{cli-cmp8g3sw.js → cli-gbfwcd3k.js} +44 -9
- package/dist/{handlers-nsg0bcye.js → cli-gjyvhmmh.js} +97 -45
- package/dist/{cli-08b07b4r.js → cli-ht5rs63n.js} +1 -1
- package/dist/{cli-jecc01cb.js → cli-j4nv2wqy.js} +2 -4
- package/dist/{cli-cd60fv6j.js → cli-j9xczhaq.js} +1 -1
- package/dist/cli-pf9q3696.js +172 -0
- package/dist/{cli-xm87hzbw.js → cli-pgj4a5fb.js} +1 -1
- package/dist/{cli-jezx9b9c.js → cli-ppm4975n.js} +9 -3
- package/dist/{cli-3z634pqe.js → cli-q88st9aj.js} +2 -2
- package/dist/{cli-3sysyjve.js → cli-r2q6pevn.js} +142 -49
- package/dist/{cli-07jd68a1.js → cli-re8z5p8p.js} +1 -1
- package/dist/{cli-qgd4sqz5.js → cli-s14agm5s.js} +121 -14
- package/dist/{cli-svbrpf5q.js → cli-sjaae6ff.js} +9872 -424
- package/dist/{cli-73gq0zxn.js → cli-vwm416m6.js} +13 -13
- package/dist/{cli-4wtq5jjv.js → cli-wbyk465z.js} +1 -1
- package/dist/{cli-3apbzgyk.js → cli-z61ykvam.js} +19 -14
- package/dist/{cli-e06a8a7y.js → cli-zkxymas5.js} +4 -3
- package/dist/cli.js +26 -25
- package/dist/{codex-adapter-jyw7a91z.js → codex-adapter-jjjk8w4m.js} +8 -9
- package/dist/{codex-hook-hfrt9shr.js → codex-hook-8jexc34x.js} +3 -3
- package/dist/{codex-session-runner-bmngj0s5.js → codex-session-runner-nd6ayxkx.js} +8 -9
- package/dist/{commands-n755g391.js → commands-9v4psyq1.js} +5 -5
- package/dist/{db-s1cgh5gv.js → db-wnt58tpe.js} +5 -5
- package/dist/dispatcher-05jh1aqk.js +74 -0
- package/dist/{e2b-p04vmtx0.js → e2b-413b8t4v.js} +1 -1
- package/dist/{google-generative-ai-tsskx7te.js → google-generative-ai-ndjmj5fa.js} +7 -7
- package/dist/{google-vertex-ppw8ydpa.js → google-vertex-fr665tqs.js} +10 -10
- package/dist/handlers-tw90pkh5.js +65 -0
- package/dist/{hook-jf0xe8zh.js → hook-123e2scb.js} +11 -12
- package/dist/{hook-h9cqrm8q.js → hook-sxe3r349.js} +11 -12
- package/dist/{http-nc6pydw5.js → http-ecsar8ez.js} +1442 -581
- package/dist/{index-ezxkds2n.js → index-16js521z.js} +335 -107
- package/dist/{index-769nc012.js → index-hw26vj40.js} +25 -19
- package/dist/{index-0wdy6gwc.js → index-nnrbpcjp.js} +25 -17
- package/dist/index-ymn7em0p.js +25 -0
- package/dist/{index-x1zcj09z.js → index-zj518gf9.js} +26 -20
- package/dist/{keepalive-nesm3xb6.js → keepalive-asqtcm4y.js} +7 -7
- package/dist/{lead-bwy6t2za.js → lead-xbfr7fvt.js} +40 -48
- package/dist/{maintenance-8w393zf0.js → maintenance-qma55qvw.js} +9 -9
- package/dist/{oauth-refresh-sweep-sh8xjy08.js → oauth-refresh-sweep-3s04c6qw.js} +6 -6
- package/dist/{onboard-25ps29h1.js → onboard-drskd386.js} +13 -4
- package/dist/{openai-codex-responses-g7w48y30.js → openai-codex-responses-wy6a43wd.js} +13 -13
- package/dist/{openai-responses-nmeyptke.js → openai-responses-6xwf7bzg.js} +19 -19
- package/dist/{opencode-adapter-dce4wskd.js → opencode-adapter-28axqa09.js} +4 -4
- package/dist/{otel-impl-b93gxnz5.js → otel-impl-943c96er.js} +1 -1
- package/dist/{pi-mono-adapter-zvshk5cj.js → pi-mono-adapter-jcqt71cg.js} +17 -19
- package/dist/{pricing-refresh-5v56x7gb.js → pricing-refresh-mx51az05.js} +7 -7
- package/dist/{rbac-roles-x55cnezn.js → rbac-roles-78baecqd.js} +13 -9
- package/dist/{rbac-roles-0p0s6pbj.js → rbac-roles-wcmrg6sv.js} +7 -7
- package/dist/{render-v2-hyd45w8b.js → render-v2-8zjntgf5.js} +7 -7
- package/dist/{seed-pricing-49gbgn96.js → seed-pricing-jqjs6cws.js} +6 -6
- package/dist/{setup-qvq64vzq.js → setup-4pks0vfk.js} +2 -2
- package/dist/work-objects-wangt792.js +165 -0
- package/dist/{worker-scj60cxg.js → worker-p2mr422x.js} +40 -48
- package/openapi.json +1365 -268
- package/package.json +4 -3
- package/src/agentmail/handlers.ts +95 -66
- package/src/be/budget-refusal-notify.ts +1 -0
- package/src/be/db/tasks/read.ts +3 -0
- package/src/be/db/tasks/write.ts +13 -1
- package/src/be/db-client.ts +5 -0
- package/src/be/db.ts +15 -5
- package/src/be/extensions/db.ts +461 -0
- package/src/be/extensions/validate.ts +107 -0
- package/src/be/memory/boot-reembed.ts +17 -12
- package/src/be/memory/index.ts +12 -0
- package/src/be/memory/providers/openai-embedding.ts +4 -0
- package/src/be/memory/types.ts +2 -0
- package/src/be/migrations/153_deferred_task_wait_members.sql +25 -0
- package/src/be/migrations/154_routing_source.sql +3 -0
- package/src/be/migrations/155_extensions.sql +66 -0
- package/src/be/migrations/156_inbox_item_state_read_at.sql +7 -0
- package/src/be/rbac-roles.ts +3 -2
- package/src/be/scripts/typecheck.ts +59 -41
- package/src/be/seed/schedules-seeder.ts +25 -2
- package/src/be/seed/workflows-seeder.ts +17 -0
- package/src/be/seed-scripts/catalog/delegate.ts +3 -1
- package/src/be/seed-skills/bundled-files.generated.json +1 -1
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/steering.ts +1 -0
- package/src/be/swarm-config-guard.ts +3 -1
- package/src/commands/credential-refresh.ts +70 -0
- package/src/commands/onboard/compose-generator.ts +14 -2
- package/src/commands/onboard/env-generator.ts +7 -0
- package/src/commands/provider-credentials.ts +2 -25
- package/src/commands/runner.ts +24 -57
- package/src/extensions/apply-task-create.ts +135 -0
- package/src/extensions/bundle-path.ts +10 -0
- package/src/extensions/contract-runtime.ts +7 -0
- package/src/extensions/contract-types.generated.ts +4 -0
- package/src/extensions/contract.ts +270 -0
- package/src/extensions/ctx.ts +186 -0
- package/src/extensions/dispatcher.ts +479 -0
- package/src/extensions/identity.ts +44 -0
- package/src/extensions/lifecycle.ts +281 -0
- package/src/extensions/loader.ts +207 -0
- package/src/extensions/post-bridge.ts +161 -0
- package/src/github/handlers.ts +185 -140
- package/src/gitlab/handlers.ts +97 -77
- package/src/heartbeat/heartbeat.ts +155 -83
- package/src/http/agents.ts +1 -1
- package/src/http/all-routes.ts +1 -0
- package/src/http/approval-requests.ts +1 -0
- package/src/http/apps.ts +14 -9
- package/src/http/config.ts +4 -1
- package/src/http/core.ts +38 -2
- package/src/http/extensions.ts +547 -0
- package/src/http/inbox-state.ts +2 -0
- package/src/http/index.ts +41 -3
- package/src/http/mcp-bridge.ts +96 -62
- package/src/http/mcp.ts +1 -1
- package/src/http/script-runs.ts +5 -0
- package/src/http/status.ts +6 -4
- package/src/http/tasks.ts +51 -30
- package/src/integrations/kapso/inbound.ts +15 -10
- package/src/jira/sync.ts +26 -16
- package/src/linear/sync.ts +26 -16
- package/src/prompts/session-templates.ts +18 -13
- package/src/providers/claude-adapter.ts +21 -8
- package/src/rbac/admission.ts +1 -1
- package/src/rbac/elevated-agents.ts +24 -0
- package/src/rbac/legacy-policy.ts +35 -6
- package/src/rbac/permissions.ts +8 -0
- package/src/scheduler/deferred-task-waits.ts +138 -27
- package/src/scheduler/schedule-task.ts +54 -24
- package/src/scheduler/scheduler.ts +108 -125
- package/src/scripts-runtime/executors/native.ts +5 -1
- package/src/scripts-runtime/executors/types.ts +5 -0
- package/src/scripts-runtime/import-allowlist.ts +79 -19
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/swarm-config.ts +8 -0
- package/src/scripts-runtime/swarm-sdk.ts +3 -0
- package/src/scripts-runtime/types/stdlib.d.ts +16 -3
- package/src/scripts-runtime/types/swarm-extension.d.ts +562 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +16 -3
- package/src/server.ts +6 -0
- package/src/slack/HEURISTICS.md +3 -1
- package/src/slack/actions.ts +21 -16
- package/src/slack/app.ts +2 -0
- package/src/slack/assistant.ts +4 -12
- package/src/slack/blocks.ts +1 -1
- package/src/slack/handlers.ts +107 -19
- package/src/slack/inbound-files.ts +9 -5
- package/src/slack/render-v2.ts +188 -38
- package/src/slack/router.ts +13 -3
- package/src/slack/steering.ts +3 -3
- package/src/slack/thread-buffer.ts +66 -23
- package/src/slack/work-objects.test.ts +252 -0
- package/src/slack/work-objects.ts +118 -0
- package/src/tasks/errors.ts +9 -0
- package/src/tasks/sibling-awareness.ts +35 -1
- package/src/tasks/worker-follow-up.ts +67 -11
- package/src/tests/acp-adapter.test.ts +10 -10
- package/src/tests/agent-fs-live-url.test.ts +40 -0
- package/src/tests/agent-fs-provision-seeder.test.ts +12 -12
- package/src/tests/api-key-tracking.test.ts +18 -18
- package/src/tests/api-key.test.ts +4 -2
- package/src/tests/apps-rbac.test.ts +1 -1
- package/src/tests/apps-spike5.test.ts +1 -1
- package/src/tests/apps-sync-engine.test.ts +8 -8
- package/src/tests/apps-user-config.test.ts +1 -1
- package/src/tests/artifact-sdk.test.ts +8 -8
- package/src/tests/asset-key-mcp.test.ts +2 -0
- package/src/tests/automation-preflight-alert.test.ts +1 -1
- package/src/tests/base-prompt.test.ts +7 -6
- package/src/tests/budget-user-scope.test.ts +1 -1
- package/src/tests/budgets-routes.test.ts +1 -1
- package/src/tests/claude-adapter-binary.test.ts +22 -40
- package/src/tests/claude-adapter-otel.test.ts +13 -7
- package/src/tests/claude-adapter.test.ts +8 -6
- package/src/tests/claude-hook-credentials.test.ts +3 -3
- package/src/tests/claude-managed-adapter.test.ts +4 -4
- package/src/tests/claude-managed-setup.test.ts +3 -3
- package/src/tests/claude-sdk-lifecycle.test.ts +1 -1
- package/src/tests/claude-sdk-transport.test.ts +6 -6
- package/src/tests/claude-stop-hook.test.ts +8 -8
- package/src/tests/claude-worker-parity.test.ts +3 -3
- package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +5 -5
- package/src/tests/codex-adapter.test.ts +7 -5
- package/src/tests/codex-app-server.test.ts +2 -2
- package/src/tests/codex-login.test.ts +15 -15
- package/src/tests/codex-oauth-credential-info.test.ts +4 -4
- package/src/tests/codex-oauth-keep-warm.test.ts +4 -4
- package/src/tests/codex-oauth-refresh-lock.test.ts +1 -1
- package/src/tests/codex-oauth-storage.test.ts +7 -7
- package/src/tests/codex-pool.test.ts +1 -1
- package/src/tests/codex-steering-hook.test.ts +1 -1
- package/src/tests/codex-swarm-events.test.ts +1 -1
- package/src/tests/config-api-only-keys.test.ts +1 -1
- package/src/tests/config-session-auth.test.ts +2 -2
- package/src/tests/connection-embedded-auth.test.ts +20 -18
- package/src/tests/core-auth.test.ts +1 -1
- package/src/tests/create-page-tool.test.ts +3 -3
- package/src/tests/credential-refresh.test.ts +115 -0
- package/src/tests/credential-wait.test.ts +2 -2
- package/src/tests/credentials.test.ts +6 -4
- package/src/tests/db-queries-oauth.test.ts +40 -40
- package/src/tests/defer-task.test.ts +73 -8
- package/src/tests/deferred-task-wait-migration.test.ts +64 -0
- package/src/tests/deferred-task-wake.test.ts +349 -8
- package/src/tests/devin-adapter.test.ts +1 -1
- package/src/tests/devin-api.test.ts +1 -1
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/e2b-dispatch.test.ts +21 -19
- package/src/tests/e2e-claude-transport.test.ts +3 -3
- package/src/tests/e2e-redact.test.ts +6 -6
- package/src/tests/ensure-token.test.ts +68 -68
- package/src/tests/entrypoint-api-readiness.test.ts +1 -1
- package/src/tests/entrypoint-codex-oauth-seed.test.ts +13 -13
- package/src/tests/env-flag.test.ts +1 -0
- package/src/tests/events-http.test.ts +1 -1
- package/src/tests/extensions-db.test.ts +216 -0
- package/src/tests/extensions-dispatcher.test.ts +275 -0
- package/src/tests/extensions-example-heartbeat-remediate.test.ts +69 -0
- package/src/tests/extensions-example-mcp-install.test.ts +63 -0
- package/src/tests/extensions-example-no-exclamation-marks.test.ts +72 -0
- package/src/tests/extensions-example-rewrite-and-suppress.test.ts +70 -0
- package/src/tests/extensions-example-route-slack-channel.test.ts +217 -0
- package/src/tests/extensions-heartbeat.test.ts +291 -0
- package/src/tests/extensions-http.test.ts +431 -0
- package/src/tests/extensions-lead-equivalence.test.ts +49 -0
- package/src/tests/extensions-lifecycle.test.ts +209 -0
- package/src/tests/extensions-loader.test.ts +95 -0
- package/src/tests/extensions-mcp-tools.test.ts +245 -0
- package/src/tests/extensions-pre-task.test.ts +487 -0
- package/src/tests/extensions-run-context.test.ts +41 -0
- package/src/tests/extensions-tool-call.test.ts +288 -0
- package/src/tests/extensions-validate.test.ts +196 -0
- package/src/tests/fixtures/extensions/bad-import/hooks.ts +8 -0
- package/src/tests/fixtures/extensions/bad-import/manifest.json +9 -0
- package/src/tests/fixtures/extensions/bad-return-shape/hooks.ts +10 -0
- package/src/tests/fixtures/extensions/bad-return-shape/manifest.json +9 -0
- package/src/tests/fixtures/extensions/block-tasks-from-source/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/block-tasks-from-source/manifest.json +9 -0
- package/src/tests/fixtures/extensions/ignore-channel/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/ignore-channel/manifest.json +9 -0
- package/src/tests/fixtures/extensions/load.ts +10 -0
- package/src/tests/fixtures/extensions/minimal/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/minimal/manifest.json +9 -0
- package/src/tests/fixtures/extensions/never-fail-long-tasks/hooks.ts +11 -0
- package/src/tests/fixtures/extensions/never-fail-long-tasks/manifest.json +9 -0
- package/src/tests/fixtures/extensions/no-exclamation-marks/hooks.ts +23 -0
- package/src/tests/fixtures/extensions/no-exclamation-marks/manifest.json +9 -0
- package/src/tests/fixtures/extensions/post-logger/hooks.ts +9 -0
- package/src/tests/fixtures/extensions/post-logger/manifest.json +9 -0
- package/src/tests/fixtures/extensions/priority-a/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/priority-a/manifest.json +9 -0
- package/src/tests/fixtures/extensions/priority-b/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/priority-b/manifest.json +9 -0
- package/src/tests/fixtures/extensions/record-only-on-tag/hooks.ts +16 -0
- package/src/tests/fixtures/extensions/record-only-on-tag/manifest.json +9 -0
- package/src/tests/fixtures/extensions/reserved-assets/hooks.ts +5 -0
- package/src/tests/fixtures/extensions/reserved-assets/manifest.json +10 -0
- package/src/tests/fixtures/extensions/rewrite-progress-prefix/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/rewrite-progress-prefix/manifest.json +9 -0
- package/src/tests/fixtures/extensions/rewrite-task-priority/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/rewrite-task-priority/manifest.json +9 -0
- package/src/tests/fixtures/extensions/route-channel-to-agent/hooks.ts +26 -0
- package/src/tests/fixtures/extensions/route-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/extensions/slow/hooks.ts +10 -0
- package/src/tests/fixtures/extensions/slow/manifest.json +9 -0
- package/src/tests/fixtures/extensions/suppress-lead-follow-up/hooks.ts +12 -0
- package/src/tests/fixtures/extensions/suppress-lead-follow-up/manifest.json +9 -0
- package/src/tests/fixtures/extensions/throws/hooks.ts +12 -0
- package/src/tests/fixtures/extensions/throws/manifest.json +9 -0
- package/src/tests/fixtures/extensions/worker-runtime/hooks.ts +5 -0
- package/src/tests/fixtures/extensions/worker-runtime/manifest.json +9 -0
- package/src/tests/fs-routes.test.ts +1 -1
- package/src/tests/gitlab-auth.test.ts +10 -10
- package/src/tests/harness-provider-resolution.test.ts +8 -5
- package/src/tests/heartbeat-reroute-decision.test.ts +1 -0
- package/src/tests/helper-credentials.test.ts +137 -0
- package/src/tests/http/context-routes.test.ts +2 -2
- package/src/tests/http-api-integration.test.ts +5 -2
- package/src/tests/http-users.test.ts +1 -1
- package/src/tests/identity-refresh.test.ts +2 -2
- package/src/tests/internal-ai/complete-structured.test.ts +2 -2
- package/src/tests/internal-ai/credentials.test.ts +19 -17
- package/src/tests/jira-metadata.test.ts +1 -1
- package/src/tests/jira-oauth.test.ts +5 -5
- package/src/tests/jira-sync.test.ts +1 -1
- package/src/tests/jira-webhook-lifecycle.test.ts +3 -3
- package/src/tests/jira-webhook.test.ts +2 -2
- package/src/tests/kapso-inbound.test.ts +2 -2
- package/src/tests/kv-http.test.ts +1 -1
- package/src/tests/kv-namespace-resolution.test.ts +1 -1
- package/src/tests/kv-page-proxy.test.ts +2 -2
- package/src/tests/launch-password-rejection.test.ts +2 -2
- package/src/tests/linear-webhook.test.ts +1 -1
- package/src/tests/mcp-oauth-dcr-reuse.test.ts +6 -6
- package/src/tests/mcp-oauth-ensure-token.test.ts +28 -22
- package/src/tests/mcp-oauth-manual-client.test.ts +16 -12
- package/src/tests/mcp-oauth-queries.test.ts +35 -32
- package/src/tests/mcp-oauth-resolve-secrets.test.ts +8 -8
- package/src/tests/mcp-oauth-wrapper.test.ts +20 -20
- package/src/tests/mcp-user-route.test.ts +1 -1
- package/src/tests/memory-edges.test.ts +1 -1
- package/src/tests/memory-edit-authorization.test.ts +32 -0
- package/src/tests/memory-rate-endpoint.test.ts +1 -1
- package/src/tests/memory-rate-tool.test.ts +2 -2
- package/src/tests/memory-rater-e2e.test.ts +1 -1
- package/src/tests/memory-rater-llm-summarizer.test.ts +3 -3
- package/src/tests/memory-rater-llm.test.ts +1 -1
- package/src/tests/model-control.test.ts +3 -0
- package/src/tests/multi-runtime-enabled-stats.test.ts +2 -2
- package/src/tests/multi-runtime-registration.test.ts +111 -17
- package/src/tests/oauth-access-token-tool.test.ts +18 -18
- package/src/tests/oauth-callback-flow.test.ts +8 -8
- package/src/tests/oauth-credential-bindings.test.ts +29 -27
- package/src/tests/oauth-keepalive.test.ts +10 -10
- package/src/tests/oauth-presets.test.ts +13 -5
- package/src/tests/oauth-refresh-failure.test.ts +9 -9
- package/src/tests/oauth-refresh-sweep.test.ts +20 -13
- package/src/tests/oauth-wrapper.test.ts +1 -1
- package/src/tests/onboard-compose.test.ts +47 -3
- package/src/tests/onboard-env.test.ts +26 -26
- package/src/tests/onboard-non-interactive.test.ts +4 -4
- package/src/tests/opencode-adapter.test.ts +1 -1
- package/src/tests/opencode-plugin.test.ts +2 -2
- package/src/tests/otel-session-cost-metrics.test.ts +1 -1
- package/src/tests/page-proxy-authed.test.ts +2 -2
- package/src/tests/page-proxy.test.ts +2 -2
- package/src/tests/page-session.test.ts +7 -7
- package/src/tests/page-viewer-auth.test.ts +2 -2
- package/src/tests/pages-authed-mode.test.ts +1 -1
- package/src/tests/pages-http.test.ts +1 -1
- package/src/tests/pages-password-mode.test.ts +1 -1
- package/src/tests/pages-public-authed-401.test.ts +1 -1
- package/src/tests/pages-public-html.test.ts +2 -2
- package/src/tests/pages-view-count.test.ts +1 -1
- package/src/tests/pi-mono-adapter.test.ts +10 -10
- package/src/tests/pi-mono-extension.test.ts +2 -2
- package/src/tests/preload.ts +5 -0
- package/src/tests/pricing-routes.test.ts +1 -1
- package/src/tests/profile-sync-warning.test.ts +8 -8
- package/src/tests/profile-sync.test.ts +8 -8
- package/src/tests/prompt-template-session.test.ts +36 -5
- package/src/tests/provider-process-group.test.ts +95 -4
- package/src/tests/providers/pi-cost.test.ts +1 -1
- package/src/tests/queue-stall-alarm.test.ts +1 -1
- package/src/tests/rbac-admission.test.ts +19 -4
- package/src/tests/rbac-charact-http.test.ts +1 -1
- package/src/tests/rbac-e2e-helpers.ts +1 -1
- package/src/tests/rbac-engine.test.ts +39 -0
- package/src/tests/realtime-room-auth.test.ts +1 -1
- package/src/tests/realtime-room-surfaces.test.ts +1 -1
- package/src/tests/reload-config.test.ts +45 -1
- package/src/tests/routing-affinity-inventory.test.ts +1 -1
- package/src/tests/routing-reason-contract.test.ts +76 -3
- package/src/tests/routing-reason-inventory.test.ts +11 -6
- package/src/tests/routing-source.test.ts +53 -0
- package/src/tests/runner-agent-fs-provision-retry.test.ts +1 -1
- package/src/tests/runner-context-preamble.test.ts +1 -1
- package/src/tests/runner-deployment-resume.test.ts +1 -1
- package/src/tests/runner-fallback-output.test.ts +1 -1
- package/src/tests/runner-identity-refresh.test.ts +1 -1
- package/src/tests/runner-skills-refresh.test.ts +1 -1
- package/src/tests/schedule-target-type.test.ts +3 -3
- package/src/tests/scheduled-tasks.test.ts +14 -5
- package/src/tests/scheduler-occurrence.test.ts +347 -0
- package/src/tests/script-apis-mcp.test.ts +1 -1
- package/src/tests/script-connections-http.test.ts +61 -58
- package/src/tests/script-connections-mcp.test.ts +1 -1
- package/src/tests/script-connections.test.ts +3 -1
- package/src/tests/script-runs-http.test.ts +15 -7
- package/src/tests/script-workflows-runtime-e2e.test.ts +1 -1
- package/src/tests/scripts-boot-reembed.test.ts +4 -0
- package/src/tests/scripts-embeddings.test.ts +4 -0
- package/src/tests/scripts-external-api.test.ts +1 -1
- package/src/tests/scripts-http.test.ts +1 -1
- package/src/tests/scripts-import-allowlist.test.ts +44 -1
- package/src/tests/scripts-mcp-e2e.test.ts +81 -1
- package/src/tests/scripts-only-gating.test.ts +4 -2
- package/src/tests/scripts-retention.test.ts +1 -1
- package/src/tests/scripts-runtime-identity.test.ts +2 -2
- package/src/tests/scripts-runtime-secret-egress.test.ts +1 -1
- package/src/tests/scripts-runtime.test.ts +6 -4
- package/src/tests/scripts-typecheck.test.ts +21 -0
- package/src/tests/sdk-allowlist.test.ts +1 -1
- package/src/tests/secret-scrubber.test.ts +38 -31
- package/src/tests/seed-registry.test.ts +46 -8
- package/src/tests/seed-schedules.test.ts +44 -9
- package/src/tests/seed-workflows.test.ts +21 -9
- package/src/tests/send-task-output-schema.test.ts +9 -1
- package/src/tests/send-task-requested-by.test.ts +1 -0
- package/src/tests/send-task-slack-routing-guard.test.ts +2 -0
- package/src/tests/session-costs-codex-recompute.test.ts +1 -1
- package/src/tests/session-costs-golden.test.ts +2 -2
- package/src/tests/session-costs-model-key-normalize.test.ts +2 -2
- package/src/tests/session-costs-recompute-all-providers.test.ts +1 -1
- package/src/tests/session-tokens.test.ts +1 -1
- package/src/tests/shutdown-error-scrubbing.test.ts +1 -1
- package/src/tests/slack-blocks.test.ts +12 -1
- package/src/tests/slack-file-tools-attachments.test.ts +1 -1
- package/src/tests/slack-inbound-files.test.ts +222 -86
- package/src/tests/slack-reaction-config.test.ts +5 -4
- package/src/tests/slack-read-boundaries.test.ts +1 -1
- package/src/tests/slack-render-v2.test.ts +196 -4
- package/src/tests/slack-router.test.ts +17 -2
- package/src/tests/slack-steering.test.ts +19 -0
- package/src/tests/status.test.ts +19 -7
- package/src/tests/steering-core.test.ts +1 -1
- package/src/tests/steering-enabled.test.ts +6 -8
- package/src/tests/steering-transport.test.ts +4 -4
- package/src/tests/store-progress-output-guidance.test.ts +34 -0
- package/src/tests/swarm-tool-result-gate.test.ts +11 -11
- package/src/tests/swarm-x-tool.test.ts +7 -5
- package/src/tests/sync-ai-toolbox-skills.test.ts +19 -0
- package/src/tests/task-supersede-resume.test.ts +1 -1
- package/src/tests/task-tool-preload-mcp.test.ts +4 -1
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tasks-requested-by-filter.test.ts +2 -2
- package/src/tests/telemetry-init.test.ts +11 -3
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/tool-output-agent-id.test.ts +1 -0
- package/src/tests/tool-registrar-no-input.test.ts +42 -1
- package/src/tests/tracker-fold.test.ts +7 -7
- package/src/tests/tracker-tools.test.ts +3 -3
- package/src/tests/ui-followup-lead-delegation.test.ts +1 -0
- package/src/tests/unified-oauth-migration.test.ts +5 -5
- package/src/tests/user-token-rest-auth.test.ts +1 -1
- package/src/tests/user-token-routes.test.ts +1 -1
- package/src/tests/whoami-route.test.ts +1 -1
- package/src/tests/workflow-agent-task.test.ts +15 -13
- package/src/tests/workflow-ctx.test.ts +1 -1
- package/src/tests/workflow-e2e.test.ts +1 -1
- package/src/tests/workflow-engine-v2.test.ts +3 -1
- package/src/tests/workflow-executors.test.ts +2 -2
- package/src/tests/workflow-http-v2.test.ts +8 -6
- package/src/tests/workflow-input-redaction.test.ts +7 -5
- package/src/tests/workflow-integration-io.test.ts +2 -2
- package/src/tests/workflow-llm.test.ts +5 -5
- package/src/tests/workflow-registry.test.ts +1 -1
- package/src/tests/workflow-swarm-script.test.ts +1 -1
- package/src/tests/workflow-triggers-v2.test.ts +23 -21
- package/src/tests/x-composio.test.ts +9 -7
- package/src/tests/x402-client.test.ts +1 -1
- package/src/tests/x402-config.test.ts +28 -41
- package/src/tools/defer-task.ts +156 -24
- package/src/tools/extension-common.ts +84 -0
- package/src/tools/extension-install.ts +65 -0
- package/src/tools/extension-list.ts +66 -0
- package/src/tools/script-common.ts +43 -18
- package/src/tools/send-task.ts +87 -105
- package/src/tools/skills/skill-publish.ts +1 -0
- package/src/tools/store-progress.ts +1 -1
- package/src/tools/task-action.ts +43 -22
- package/src/tools/task-tool-ctx.ts +2 -0
- package/src/tools/templates.ts +2 -1
- package/src/tools/tool-config.ts +3 -1
- package/src/tools/utils.ts +140 -16
- package/src/types.ts +144 -0
- package/src/utils/constants.ts +7 -1
- package/src/utils/credentials.test.ts +16 -16
- package/src/utils/multi-runtime.ts +2 -2
- package/src/utils/steering-enabled.ts +4 -4
- package/src/workflows/executors/agent-task.ts +18 -3
- package/templates/ai-toolbox.manifest.json +7 -1
- package/templates/extensions/README.md +17 -0
- package/templates/extensions/notify-on-complete/README.md +11 -0
- package/templates/extensions/notify-on-complete/hooks.ts +61 -0
- package/templates/extensions/notify-on-complete/manifest.json +7 -0
- package/templates/extensions/require-ticket-ref/README.md +11 -0
- package/templates/extensions/require-ticket-ref/hooks.ts +30 -0
- package/templates/extensions/require-ticket-ref/manifest.json +7 -0
- package/templates/extensions/require-verification-note/README.md +11 -0
- package/templates/extensions/require-verification-note/hooks.ts +32 -0
- package/templates/extensions/require-verification-note/manifest.json +7 -0
- package/templates/schedules/daily-hn-briefing/config.json +1 -1
- package/templates/schedules/gtm-weekly-review/config.json +1 -1
- package/templates/schedules/weekly-code-health-reports/config.json +1 -1
- package/templates/schedules/weekly-dependabot-triage/config.json +1 -1
- package/templates/schedules/weekly-dora-metrics/config.json +1 -1
- package/templates/schedules/weekly-harness-upgrade-check/config.json +1 -1
- package/templates/skills/delegate-work/files/scripts/codex-exec.sh +1 -1
- package/templates/skills/scheduling/content.md +2 -0
- package/templates/skills/serply-search/SKILL.md +95 -0
- package/templates/skills/serply-search/config.json +13 -0
- package/templates/skills/serply-search/content.md +90 -0
- package/templates/skills/swarm-extensions/config.json +14 -0
- package/templates/skills/swarm-extensions/content.md +120 -0
- package/templates/skills/swarm-scripts/SKILL.md +2 -2
- package/templates/skills/swarm-scripts/content.md +2 -2
- package/templates/workflows/claude-code-changelog-watch/config.json +1 -1
- package/templates/workflows/gsc-topic-miner/config.json +1 -1
- package/templates/workflows/linear-drain-loop/config.json +1 -1
- package/templates/workflows/llm-safe-release-context/config.json +1 -1
- package/templates/workflows/ralph-loop/config.json +1 -1
- package/dist/cli-7fehefdf.js +0 -562
- package/dist/cli-ayvy5kde.js +0 -164
- package/dist/cli-ddfw1mc4.js +0 -4322
- package/dist/cli-hzqmgcm2.js +0 -3066
- package/dist/cli-j4d4f6hv.js +0 -338
- package/dist/cli-qgm2pfpq.js +0 -6377
- package/dist/cli-sdzq01t9.js +0 -823
- package/dist/cli-xvkmedgn.js +0 -332
- package/dist/cli-y3pq4v9g.js +0 -664
- package/dist/{anthropic-messages-vs2rabzp.js → anthropic-messages-2y8nktar.js} +19 -19
- package/dist/{claude-managed-setup-f5pmsyrp.js → claude-managed-setup-48dwg9bv.js} +3 -3
- package/dist/{cli-81r683bv.js → cli-ch38q5z4.js} +0 -0
- package/dist/{cli-6664w7y4.js → cli-kj76p1ez.js} +8 -8
- package/dist/{cli-c71mg51n.js → cli-r2fpe7cx.js} +5 -5
- package/dist/{cli-4xz3pmrq.js → cli-y6x0gqtg.js} +16 -16
- package/dist/{index-aa3sa6s8.js → index-2wsdsnmm.js} +1 -1
- package/dist/{mistral-conversations-4ryk7h83.js → mistral-conversations-qhr84ph3.js} +9 -9
- package/dist/{openai-completions-0bqmsajw.js → openai-completions-32rdwmze.js} +19 -19
- package/dist/{openrouter-images-qx18fyp8.js → openrouter-images-9f9ek4rw.js} +3 -3
- package/dist/{pi-messages-79jvzz1d.js → pi-messages-b1mbr6gp.js} +4 -4
|
@@ -205,7 +205,7 @@ describe("PiMonoAdapter.createSession — MCP runtime identity header", () => {
|
|
|
205
205
|
agentId: "test-agent",
|
|
206
206
|
taskId: "test-task",
|
|
207
207
|
apiUrl,
|
|
208
|
-
apiKey: "test-key",
|
|
208
|
+
apiKey: "example-test-key",
|
|
209
209
|
cwd: "/tmp",
|
|
210
210
|
logFile: `/tmp/pi-mcp-header-test-${Date.now()}-${Math.random().toString(36).slice(2)}.log`,
|
|
211
211
|
};
|
|
@@ -438,28 +438,28 @@ describe("resolveModel — OpenRouter reroute for anthropic shortnames", () => {
|
|
|
438
438
|
|
|
439
439
|
describe("createPiRuntimeAuth", () => {
|
|
440
440
|
test("threads resolved OpenRouter key into pi runtime auth without process.env", async () => {
|
|
441
|
-
const modelRuntime = await createPiRuntimeAuth({ OPENROUTER_API_KEY: "sk-or-runtime" });
|
|
441
|
+
const modelRuntime = await createPiRuntimeAuth({ OPENROUTER_API_KEY: "example-sk-or-runtime" });
|
|
442
442
|
|
|
443
443
|
await expect(modelRuntime.getAuth("openrouter")).resolves.toMatchObject({
|
|
444
|
-
auth: { apiKey: "sk-or-runtime" },
|
|
444
|
+
auth: { apiKey: "example-sk-or-runtime" },
|
|
445
445
|
});
|
|
446
446
|
});
|
|
447
447
|
|
|
448
448
|
test("supports all pi env-backed providers", async () => {
|
|
449
449
|
const modelRuntime = await createPiRuntimeAuth({
|
|
450
|
-
ANTHROPIC_API_KEY: "sk-ant-runtime",
|
|
451
|
-
OPENAI_API_KEY: "sk-openai-runtime",
|
|
452
|
-
GOOGLE_API_KEY: "sk-google-runtime",
|
|
450
|
+
ANTHROPIC_API_KEY: "example-sk-ant-runtime",
|
|
451
|
+
OPENAI_API_KEY: "example-sk-openai-runtime",
|
|
452
|
+
GOOGLE_API_KEY: "example-sk-google-runtime",
|
|
453
453
|
});
|
|
454
454
|
|
|
455
455
|
await expect(modelRuntime.getAuth("anthropic")).resolves.toMatchObject({
|
|
456
|
-
auth: { apiKey: "sk-ant-runtime" },
|
|
456
|
+
auth: { apiKey: "example-sk-ant-runtime" },
|
|
457
457
|
});
|
|
458
458
|
await expect(modelRuntime.getAuth("openai")).resolves.toMatchObject({
|
|
459
|
-
auth: { apiKey: "sk-openai-runtime" },
|
|
459
|
+
auth: { apiKey: "example-sk-openai-runtime" },
|
|
460
460
|
});
|
|
461
461
|
await expect(modelRuntime.getAuth("google")).resolves.toMatchObject({
|
|
462
|
-
auth: { apiKey: "sk-google-runtime" },
|
|
462
|
+
auth: { apiKey: "example-sk-google-runtime" },
|
|
463
463
|
});
|
|
464
464
|
});
|
|
465
465
|
});
|
|
@@ -641,7 +641,7 @@ function makeSessionConfig(logFile: string): ProviderSessionConfig {
|
|
|
641
641
|
agentId: "test-agent-id",
|
|
642
642
|
taskId: "test-task-id",
|
|
643
643
|
apiUrl: "http://localhost:3013",
|
|
644
|
-
apiKey: "test-key",
|
|
644
|
+
apiKey: "example-test-key",
|
|
645
645
|
cwd: "/tmp",
|
|
646
646
|
logFile,
|
|
647
647
|
iteration: 1,
|
|
@@ -27,7 +27,7 @@ import { summarizeSessionForPi } from "../providers/pi-mono-extension";
|
|
|
27
27
|
function makeConfig(): SwarmHooksConfig {
|
|
28
28
|
return {
|
|
29
29
|
apiUrl: "http://localhost:3013",
|
|
30
|
-
apiKey: "test-key",
|
|
30
|
+
apiKey: "example-test-key",
|
|
31
31
|
agentId: "agent-pi-1",
|
|
32
32
|
taskId: "task-pi-1",
|
|
33
33
|
isLead: false,
|
|
@@ -135,7 +135,7 @@ describe("summarizeSessionForPi", () => {
|
|
|
135
135
|
expect(lastRunSummarizeArgs!.taskContext.sourceTaskId).toBe("task-pi-1");
|
|
136
136
|
expect(lastRunSummarizeArgs!.taskContext.agentId).toBe("agent-pi-1");
|
|
137
137
|
expect(lastRunSummarizeArgs!.apiUrl).toBe("http://localhost:3013");
|
|
138
|
-
expect(lastRunSummarizeArgs!.apiKey).toBe("test-key");
|
|
138
|
+
expect(lastRunSummarizeArgs!.apiKey).toBe("example-test-key");
|
|
139
139
|
|
|
140
140
|
const indexCalls = fetchCalls.filter((c) => c.url.endsWith("/api/memory/index"));
|
|
141
141
|
expect(indexCalls.length).toBe(1);
|
package/src/tests/preload.ts
CHANGED
|
@@ -73,6 +73,11 @@ const testTemplateGlobals = globalThis as typeof globalThis & {
|
|
|
73
73
|
// so removing the key just forces the fast failure path (~0ms vs ~2s of API calls).
|
|
74
74
|
delete process.env.OPENROUTER_API_KEY;
|
|
75
75
|
|
|
76
|
+
// Deployment flags must not change the test suite's default registration and
|
|
77
|
+
// task-admission contracts. Multi-runtime suites opt in by setting this to "true"
|
|
78
|
+
// and restore it themselves. Tests of the code default explicitly delete it.
|
|
79
|
+
process.env.MULTI_RUNTIME_ENABLED = "false";
|
|
80
|
+
|
|
76
81
|
// Fixed fixture key for deterministic test runs (32 bytes of 0x00, base64-encoded).
|
|
77
82
|
// Never used in production — the key bootstrap's `:memory:` special case requires
|
|
78
83
|
// an explicit env-var key, so we set one here before initDb runs. Individual tests
|
|
@@ -20,7 +20,7 @@ import { CODEX_MODEL_PRICING } from "../providers/codex-models";
|
|
|
20
20
|
import { listenOnFreePort } from "./test-net";
|
|
21
21
|
|
|
22
22
|
const TEST_DB_PATH = "./test-pricing-routes.sqlite";
|
|
23
|
-
const API_KEY = "test-pricing-secret-key";
|
|
23
|
+
const API_KEY = "example-test-pricing-secret-key";
|
|
24
24
|
|
|
25
25
|
async function removeDbFiles(path: string): Promise<void> {
|
|
26
26
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
@@ -72,7 +72,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
72
72
|
"ORIGINAL TASK PROMPT",
|
|
73
73
|
{
|
|
74
74
|
apiUrl: "https://api.example.test",
|
|
75
|
-
apiKey: "secret-key",
|
|
75
|
+
apiKey: "example-secret-key",
|
|
76
76
|
agentId: "agent-1",
|
|
77
77
|
},
|
|
78
78
|
fetchImpl,
|
|
@@ -92,7 +92,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
92
92
|
const taskPrompt = "/work-on-task child-id\n\nTask: follow up";
|
|
93
93
|
const followUp = await prependProfileSyncRejectionBanner(
|
|
94
94
|
prependContextPreamble(taskPrompt, context),
|
|
95
|
-
{ apiUrl: "https://api.example.test", apiKey: "secret-key", agentId: "agent-1" },
|
|
95
|
+
{ apiUrl: "https://api.example.test", apiKey: "example-secret-key", agentId: "agent-1" },
|
|
96
96
|
fetchImpl,
|
|
97
97
|
);
|
|
98
98
|
expect(followUp.prompt).toStartWith("/work-on-task child-id\n");
|
|
@@ -120,7 +120,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
120
120
|
const banner = await fetchProfileSyncRejectionBanner(
|
|
121
121
|
{
|
|
122
122
|
apiUrl: "https://api.example.test",
|
|
123
|
-
apiKey: "secret-key",
|
|
123
|
+
apiKey: "example-secret-key",
|
|
124
124
|
agentId: "agent-1",
|
|
125
125
|
},
|
|
126
126
|
fetchImpl,
|
|
@@ -153,7 +153,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
153
153
|
const banner = await fetchProfileSyncRejectionBanner(
|
|
154
154
|
{
|
|
155
155
|
apiUrl: "https://api.example.test",
|
|
156
|
-
apiKey: "secret-key",
|
|
156
|
+
apiKey: "example-secret-key",
|
|
157
157
|
agentId: "agent-1",
|
|
158
158
|
},
|
|
159
159
|
fetchImpl,
|
|
@@ -190,7 +190,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
190
190
|
const banner = await fetchProfileSyncRejectionBanner(
|
|
191
191
|
{
|
|
192
192
|
apiUrl: "https://api.example.test",
|
|
193
|
-
apiKey: "secret-key",
|
|
193
|
+
apiKey: "example-secret-key",
|
|
194
194
|
agentId: "agent-1",
|
|
195
195
|
},
|
|
196
196
|
fetchImpl,
|
|
@@ -219,7 +219,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
219
219
|
}) as typeof fetch;
|
|
220
220
|
const config = {
|
|
221
221
|
apiUrl: "https://api.example.test",
|
|
222
|
-
apiKey: "secret-key",
|
|
222
|
+
apiKey: "example-secret-key",
|
|
223
223
|
agentId: "agent-1",
|
|
224
224
|
claudeMdPath: WORKSPACE_CLAUDE_MD_PATH,
|
|
225
225
|
};
|
|
@@ -266,7 +266,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
266
266
|
const banner = await fetchProfileSyncRejectionBanner(
|
|
267
267
|
{
|
|
268
268
|
apiUrl: "https://api.example.test",
|
|
269
|
-
apiKey: "secret-key",
|
|
269
|
+
apiKey: "example-secret-key",
|
|
270
270
|
agentId: "agent-1",
|
|
271
271
|
},
|
|
272
272
|
fetchImpl,
|
|
@@ -282,7 +282,7 @@ describe("profile sync rejection session warning", () => {
|
|
|
282
282
|
const banner = await fetchProfileSyncRejectionBanner(
|
|
283
283
|
{
|
|
284
284
|
apiUrl: "https://api.example.test",
|
|
285
|
-
apiKey: "secret-key",
|
|
285
|
+
apiKey: "example-secret-key",
|
|
286
286
|
agentId: "agent-1",
|
|
287
287
|
},
|
|
288
288
|
(async () => new Response("unavailable", { status: 503 })) as typeof fetch,
|
|
@@ -97,7 +97,7 @@ describe("profile divergence audit", () => {
|
|
|
97
97
|
{
|
|
98
98
|
agentId: "agent-1",
|
|
99
99
|
apiUrl: "https://api.example.test",
|
|
100
|
-
apiKey: "secret-key",
|
|
100
|
+
apiKey: "example-secret-key",
|
|
101
101
|
claudeMdPath: WORKSPACE_CLAUDE_MD_PATH,
|
|
102
102
|
},
|
|
103
103
|
{ fetchImpl, readFile },
|
|
@@ -131,7 +131,7 @@ describe("profile divergence audit", () => {
|
|
|
131
131
|
{
|
|
132
132
|
agentId: "agent-codex",
|
|
133
133
|
apiUrl: "https://api.example.test",
|
|
134
|
-
apiKey: "secret-key",
|
|
134
|
+
apiKey: "example-secret-key",
|
|
135
135
|
},
|
|
136
136
|
{ fetchImpl, readFile },
|
|
137
137
|
);
|
|
@@ -153,7 +153,7 @@ describe("profile divergence audit", () => {
|
|
|
153
153
|
{
|
|
154
154
|
agentId: "agent-unregistered",
|
|
155
155
|
apiUrl: "https://api.example.test",
|
|
156
|
-
apiKey: "secret-key",
|
|
156
|
+
apiKey: "example-secret-key",
|
|
157
157
|
},
|
|
158
158
|
{ fetchImpl, readFile: async () => undefined },
|
|
159
159
|
),
|
|
@@ -172,7 +172,7 @@ describe("profile divergence audit", () => {
|
|
|
172
172
|
{
|
|
173
173
|
agentId: "agent-unset",
|
|
174
174
|
apiUrl: "https://api.example.test",
|
|
175
|
-
apiKey: "secret-key",
|
|
175
|
+
apiKey: "example-secret-key",
|
|
176
176
|
claudeMdPath: WORKSPACE_CLAUDE_MD_PATH,
|
|
177
177
|
},
|
|
178
178
|
{ fetchImpl, readFile },
|
|
@@ -415,7 +415,7 @@ describe("postProfileUpdate (non-2xx is surfaced, not swallowed)", () => {
|
|
|
415
415
|
const opts = {
|
|
416
416
|
agentId: "agent-1",
|
|
417
417
|
apiUrl: "https://api.example.test",
|
|
418
|
-
apiKey: "secret-key",
|
|
418
|
+
apiKey: "example-secret-key",
|
|
419
419
|
};
|
|
420
420
|
const payload = {
|
|
421
421
|
label: "setup",
|
|
@@ -477,7 +477,7 @@ describe("postProfileUpdate (non-2xx is surfaced, not swallowed)", () => {
|
|
|
477
477
|
expect(capturedUrl).toBe("https://api.example.test/api/agents/agent-1/profile");
|
|
478
478
|
expect(capturedInit?.method).toBe("PUT");
|
|
479
479
|
const headers = capturedInit?.headers as Record<string, string>;
|
|
480
|
-
expect(headers.Authorization).toBe("Bearer secret-key");
|
|
480
|
+
expect(headers.Authorization).toBe("Bearer example-secret-key");
|
|
481
481
|
expect(headers["X-Agent-ID"]).toBe("agent-1");
|
|
482
482
|
expect(JSON.parse(String(capturedInit?.body))).toEqual(payload.body);
|
|
483
483
|
});
|
|
@@ -498,7 +498,7 @@ describe("syncProfileFilesToServer (orchestration is non-fatal)", () => {
|
|
|
498
498
|
await syncProfileFilesToServer({
|
|
499
499
|
agentId: "agent-1",
|
|
500
500
|
apiUrl: "https://api.example.test",
|
|
501
|
-
apiKey: "secret-key",
|
|
501
|
+
apiKey: "example-secret-key",
|
|
502
502
|
changeSource: "session_sync",
|
|
503
503
|
fields: ["claude"],
|
|
504
504
|
claudeMdLock: { path: lockPath, waitMs: 100 },
|
|
@@ -522,7 +522,7 @@ describe("syncProfileFilesToServer (orchestration is non-fatal)", () => {
|
|
|
522
522
|
syncProfileFilesToServer({
|
|
523
523
|
agentId: "agent-1",
|
|
524
524
|
apiUrl: "https://api.example.test",
|
|
525
|
-
apiKey: "secret-key",
|
|
525
|
+
apiKey: "example-secret-key",
|
|
526
526
|
changeSource: "session_sync",
|
|
527
527
|
// No files on a CI box → typically no payloads; still must never throw.
|
|
528
528
|
claudeMdLock: { path: join(tmpdir(), `claude-md-${crypto.randomUUID()}.lock`) },
|
|
@@ -227,7 +227,7 @@ describe("Session templates: MUST pointers", () => {
|
|
|
227
227
|
test("the lead contract names the delegation tools", () => {
|
|
228
228
|
const result = resolveTemplate("system.agent.lead", {});
|
|
229
229
|
expect(result.text).toContain(
|
|
230
|
-
"`send-task`: include `routingReason` with `agentId`. Read results via `get-task-details`.",
|
|
230
|
+
"`send-task`: include `routingReason` and `routingNote` (at least 10 characters after trim, maximum 200) with `agentId`. Read results via `get-task-details`.",
|
|
231
231
|
);
|
|
232
232
|
});
|
|
233
233
|
|
|
@@ -264,17 +264,48 @@ describe("Session templates: composite resolution", () => {
|
|
|
264
264
|
expect(result.text).not.toContain("{{@template[");
|
|
265
265
|
expect(result.text).toContain("You are Ada,");
|
|
266
266
|
expect(result.text).toContain("composite-agent-001");
|
|
267
|
-
//
|
|
267
|
+
// Bind the budget to task output in the shared writing block itself,
|
|
268
|
+
// so a budget elsewhere in the composite cannot mask a reply-only rule.
|
|
269
|
+
const writingBlock = result.text.split("## How you write\n")[1]?.split("\n## ")[0];
|
|
270
|
+
expect(writingBlock).toContain("task output (`output` or a remote final message)");
|
|
271
|
+
expect(writingBlock).toContain(
|
|
272
|
+
"Routine replies and free-text task output: under 120 words by default",
|
|
273
|
+
);
|
|
274
|
+
expect(writingBlock).toContain("requested depth, enumerated results, essential evidence");
|
|
275
|
+
expect(writingBlock).toContain("longer output required by the task's `outputSchema`");
|
|
276
|
+
expect(writingBlock).toContain("Preserve investigation and required artifacts");
|
|
277
|
+
expect(writingBlock).toContain(
|
|
278
|
+
"Schema exemptions apply to `outputSchema`-constrained completions",
|
|
279
|
+
);
|
|
280
|
+
expect(writingBlock).toContain("free-text `output` follows the target");
|
|
281
|
+
expect(writingBlock).toContain("link documents instead of inlining them");
|
|
282
|
+
expect(writingBlock).not.toContain("schema-defined output");
|
|
268
283
|
expect(result.text).toContain("Simple replies: one to three sentences");
|
|
269
|
-
expect(result.text).toContain("Routine replies: under 120 words");
|
|
270
|
-
expect(result.text).toContain("Use more detail for requested depth or essential evidence");
|
|
271
284
|
expect(result.text).toContain("Use the `comms` skill when available");
|
|
272
285
|
expect(result.text).toContain("Follow the current request and Requester Profile");
|
|
273
|
-
expect(result.text).toContain("Do not shorten investigation, required artifacts");
|
|
274
286
|
expect(result.text).toContain("Output schemas and channel delivery rules");
|
|
275
287
|
});
|
|
276
288
|
}
|
|
277
289
|
|
|
290
|
+
for (const eventType of ["system.agent.worker", "system.agent.worker.remote"]) {
|
|
291
|
+
test(`${eventType} pairs completion requirements with the output budget`, () => {
|
|
292
|
+
const { text } = resolveTemplate(eventType, {});
|
|
293
|
+
expect(text).toContain("under 120 words by default");
|
|
294
|
+
expect(text).toContain("Link documents instead of inlining them; omit process narration");
|
|
295
|
+
expect(text).toContain("under 120 words by default, with the exceptions in How you write");
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
for (const eventType of ["system.agent.slack", "system.agent.scripts_only_mode.slack"]) {
|
|
300
|
+
test(`${eventType} applies the output budget to the engine-owned card`, () => {
|
|
301
|
+
const { text } = resolveTemplate(eventType, { slackChannelId: "C123", slackThreadTs: "1.2" });
|
|
302
|
+
expect(text).toContain("The outcome card publishes your `output` verbatim");
|
|
303
|
+
expect(text).toContain(
|
|
304
|
+
"Keep free-text `output` under 120 words by default, with the exceptions in How you write",
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
278
309
|
test("lead and worker differ only in the contract block", () => {
|
|
279
310
|
const lead = resolveTemplate("system.session.lead", { ...vars, role: "lead" }).text;
|
|
280
311
|
const worker = resolveTemplate("system.session.worker", vars).text;
|
|
@@ -3,7 +3,7 @@ import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { ClaudeAdapter } from "../providers/claude-adapter";
|
|
6
|
-
import type { ProviderSessionConfig } from "../providers/types";
|
|
6
|
+
import type { ProviderSession, ProviderSessionConfig } from "../providers/types";
|
|
7
7
|
import { CHILD_PROCESS_TEST_BUDGET_MS } from "./test-proc";
|
|
8
8
|
|
|
9
9
|
function processExists(pid: number): boolean {
|
|
@@ -31,6 +31,18 @@ async function waitForProcessGone(pid: number, timeoutMs: number): Promise<boole
|
|
|
31
31
|
return true;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
async function waitForPidFile(path: string, timeoutMs: number): Promise<number> {
|
|
35
|
+
const deadline = Date.now() + timeoutMs;
|
|
36
|
+
while (Date.now() < deadline) {
|
|
37
|
+
if (await Bun.file(path).exists()) {
|
|
38
|
+
const pid = Number(await Bun.file(path).text());
|
|
39
|
+
if (Number.isInteger(pid) && pid > 0) return pid;
|
|
40
|
+
}
|
|
41
|
+
await Bun.sleep(20);
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Timed out waiting for PID file: ${path}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
const PROCESS_GONE_TIMEOUT_MS = 5_000;
|
|
35
47
|
|
|
36
48
|
describe("provider process groups", () => {
|
|
@@ -44,6 +56,7 @@ describe("provider process groups", () => {
|
|
|
44
56
|
const grandchildPidPath = join(dir, "grandchild.pid");
|
|
45
57
|
const logFile = join(dir, "claude.jsonl");
|
|
46
58
|
let grandchildPid: number | undefined;
|
|
59
|
+
let session: ProviderSession | undefined;
|
|
47
60
|
|
|
48
61
|
await writeFile(
|
|
49
62
|
fixturePath,
|
|
@@ -75,21 +88,23 @@ describe("provider process groups", () => {
|
|
|
75
88
|
logFile,
|
|
76
89
|
env: {
|
|
77
90
|
PATH: process.env.PATH ?? "/usr/bin:/bin",
|
|
78
|
-
CLAUDE_CODE_OAUTH_TOKEN: "test-oauth-token",
|
|
91
|
+
CLAUDE_CODE_OAUTH_TOKEN: "example-test-oauth-token",
|
|
79
92
|
CLAUDE_BINARY: `bun ${fixturePath}`,
|
|
93
|
+
CLAUDE_TRANSPORT: "cli",
|
|
80
94
|
GRANDCHILD_PID_FILE: grandchildPidPath,
|
|
81
95
|
},
|
|
82
96
|
};
|
|
83
97
|
|
|
84
98
|
try {
|
|
85
|
-
|
|
99
|
+
session = await new ClaudeAdapter(async () => {}).createSession(config);
|
|
100
|
+
grandchildPid = await waitForPidFile(grandchildPidPath, PROCESS_GONE_TIMEOUT_MS);
|
|
86
101
|
const result = await session.waitForCompletion();
|
|
87
|
-
grandchildPid = Number(await Bun.file(grandchildPidPath).text());
|
|
88
102
|
|
|
89
103
|
expect(result.exitCode).toBe(0);
|
|
90
104
|
expect(Number.isInteger(grandchildPid)).toBe(true);
|
|
91
105
|
expect(await waitForProcessGone(grandchildPid, PROCESS_GONE_TIMEOUT_MS)).toBe(true);
|
|
92
106
|
} finally {
|
|
107
|
+
await session?.abort();
|
|
93
108
|
if (grandchildPid && processExists(grandchildPid)) {
|
|
94
109
|
try {
|
|
95
110
|
process.kill(grandchildPid, "SIGKILL");
|
|
@@ -102,4 +117,80 @@ describe("provider process groups", () => {
|
|
|
102
117
|
},
|
|
103
118
|
CHILD_PROCESS_TEST_BUDGET_MS,
|
|
104
119
|
);
|
|
120
|
+
|
|
121
|
+
posixTest(
|
|
122
|
+
"Claude adapter bounds a hanging version probe",
|
|
123
|
+
async () => {
|
|
124
|
+
const dir = await mkdtemp(join(tmpdir(), "claude-version-probe-"));
|
|
125
|
+
const fixturePath = join(dir, "fake-claude.ts");
|
|
126
|
+
const versionChildPidPath = join(dir, "version-child.pid");
|
|
127
|
+
const logFile = join(dir, "claude.jsonl");
|
|
128
|
+
let session: ProviderSession | undefined;
|
|
129
|
+
let versionChildPid: number | undefined;
|
|
130
|
+
|
|
131
|
+
await writeFile(
|
|
132
|
+
fixturePath,
|
|
133
|
+
`if (Bun.argv.includes("--version")) {
|
|
134
|
+
const child = Bun.spawn(["sh", "-c", "trap '' TERM; while :; do sleep 1; done"], {
|
|
135
|
+
stdin: "ignore",
|
|
136
|
+
stdout: "inherit",
|
|
137
|
+
stderr: "inherit",
|
|
138
|
+
});
|
|
139
|
+
child.unref();
|
|
140
|
+
await Bun.write(process.env.VERSION_CHILD_PID_FILE!, String(child.pid));
|
|
141
|
+
await Bun.sleep(60_000);
|
|
142
|
+
} else {
|
|
143
|
+
console.log(JSON.stringify({ type: "result", total_cost_usd: 0, is_error: false }));
|
|
144
|
+
}
|
|
145
|
+
`,
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const config: ProviderSessionConfig = {
|
|
149
|
+
prompt: "finish immediately",
|
|
150
|
+
systemPrompt: "",
|
|
151
|
+
model: "sonnet",
|
|
152
|
+
role: "worker",
|
|
153
|
+
agentId: "test-agent-id",
|
|
154
|
+
taskId: crypto.randomUUID(),
|
|
155
|
+
apiUrl: "",
|
|
156
|
+
apiKey: "",
|
|
157
|
+
cwd: dir,
|
|
158
|
+
logFile,
|
|
159
|
+
env: {
|
|
160
|
+
PATH: process.env.PATH ?? "/usr/bin:/bin",
|
|
161
|
+
CLAUDE_CODE_OAUTH_TOKEN: "test-oauth-token",
|
|
162
|
+
CLAUDE_BINARY: `bun ${fixturePath}`,
|
|
163
|
+
CLAUDE_TRANSPORT: "cli",
|
|
164
|
+
VERSION_CHILD_PID_FILE: versionChildPidPath,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const startedAt = performance.now();
|
|
169
|
+
try {
|
|
170
|
+
session = await new ClaudeAdapter(async () => {}).createSession(config);
|
|
171
|
+
const sessionCreationMs = performance.now() - startedAt;
|
|
172
|
+
versionChildPid = await waitForPidFile(versionChildPidPath, PROCESS_GONE_TIMEOUT_MS);
|
|
173
|
+
|
|
174
|
+
expect(sessionCreationMs).toBeLessThan(PROCESS_GONE_TIMEOUT_MS);
|
|
175
|
+
expect(await waitForProcessGone(versionChildPid, PROCESS_GONE_TIMEOUT_MS)).toBe(true);
|
|
176
|
+
expect(session.deliverSteering).toBeUndefined();
|
|
177
|
+
const result = await session.waitForCompletion();
|
|
178
|
+
expect(result.exitCode).toBe(0);
|
|
179
|
+
} finally {
|
|
180
|
+
await session?.abort();
|
|
181
|
+
if (!versionChildPid && (await Bun.file(versionChildPidPath).exists())) {
|
|
182
|
+
versionChildPid = Number(await Bun.file(versionChildPidPath).text());
|
|
183
|
+
}
|
|
184
|
+
if (versionChildPid && processExists(versionChildPid)) {
|
|
185
|
+
try {
|
|
186
|
+
process.kill(versionChildPid, "SIGKILL");
|
|
187
|
+
} catch {
|
|
188
|
+
// Already reaped.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
await rm(dir, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
CHILD_PROCESS_TEST_BUDGET_MS,
|
|
195
|
+
);
|
|
105
196
|
});
|
|
@@ -213,7 +213,7 @@ describe("queue stall alarm", () => {
|
|
|
213
213
|
});
|
|
214
214
|
|
|
215
215
|
test("scrubs secrets from notification failures before logging", () => {
|
|
216
|
-
const token = "ghp_1234567890abcdefABCDEF1234567890ABCD";
|
|
216
|
+
const token = "example-ghp_1234567890abcdefABCDEF1234567890ABCD";
|
|
217
217
|
|
|
218
218
|
const output = _test.formatCheckFailure(new Error(`Slack rejected token ${token}`));
|
|
219
219
|
|
|
@@ -22,11 +22,11 @@ import { handleFs } from "../http/fs";
|
|
|
22
22
|
import { handleMcpOAuth } from "../http/mcp-oauth";
|
|
23
23
|
import { handleTasks } from "../http/tasks";
|
|
24
24
|
import { getPathSegments, parseQueryParams } from "../http/utils";
|
|
25
|
-
import { decideAdmission, decideToolAdmission, type PermissionVerb } from "../rbac";
|
|
25
|
+
import { decideAdmission, decideToolAdmission, isRbacEnabled, type PermissionVerb } from "../rbac";
|
|
26
26
|
import { listenOnFreePort } from "./test-net";
|
|
27
27
|
|
|
28
28
|
const TEST_DB_PATH = "./test-rbac-admission.sqlite";
|
|
29
|
-
const API_KEY = "test-api-key";
|
|
29
|
+
const API_KEY = "example-test-api-key";
|
|
30
30
|
const LEAD_ID = "aaaa7000-0000-4000-8000-000000000001";
|
|
31
31
|
const ACTOR: IdentityActor = { kind: "operator", id: "op:test" };
|
|
32
32
|
const MISSING_TASK_ID = "00000000-0000-4000-8000-000000000000";
|
|
@@ -149,7 +149,7 @@ beforeEach(async () => {
|
|
|
149
149
|
closeDb();
|
|
150
150
|
await removeDbFiles();
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
process.env.RBAC_ENABLED = "false";
|
|
153
153
|
delete process.env.RBAC_AUDIT_DISABLED;
|
|
154
154
|
delete process.env.RBAC_AUDIT_RETENTION_DAYS;
|
|
155
155
|
|
|
@@ -387,7 +387,7 @@ describe("handleCore admission wiring", () => {
|
|
|
387
387
|
expect(admin.status).not.toBe(403);
|
|
388
388
|
expect(admin.status).toBe(404);
|
|
389
389
|
|
|
390
|
-
|
|
390
|
+
process.env.RBAC_ENABLED = "false";
|
|
391
391
|
|
|
392
392
|
const flagOff = await api(port, "GET", "/api/mcp-oauth/missing-server/authorize-url", {
|
|
393
393
|
bearer: requesterToken,
|
|
@@ -482,3 +482,18 @@ describe("handleCore admission wiring", () => {
|
|
|
482
482
|
});
|
|
483
483
|
});
|
|
484
484
|
});
|
|
485
|
+
|
|
486
|
+
test("RBAC defaults on and accepts explicit opt-outs", () => {
|
|
487
|
+
const previous = process.env.RBAC_ENABLED;
|
|
488
|
+
try {
|
|
489
|
+
delete process.env.RBAC_ENABLED;
|
|
490
|
+
expect(isRbacEnabled()).toBe(true);
|
|
491
|
+
for (const value of ["false", "0"]) {
|
|
492
|
+
process.env.RBAC_ENABLED = value;
|
|
493
|
+
expect(isRbacEnabled()).toBe(false);
|
|
494
|
+
}
|
|
495
|
+
} finally {
|
|
496
|
+
if (previous === undefined) delete process.env.RBAC_ENABLED;
|
|
497
|
+
else process.env.RBAC_ENABLED = previous;
|
|
498
|
+
}
|
|
499
|
+
});
|
|
@@ -50,7 +50,7 @@ import { listenOnFreePort } from "./test-net";
|
|
|
50
50
|
|
|
51
51
|
const TEST_DB_PATH = "./test-rbac-charact-http.sqlite";
|
|
52
52
|
const TEST_FS_DIR = "./test-rbac-charact-http-data";
|
|
53
|
-
const API_KEY = "test-rbac-http-key";
|
|
53
|
+
const API_KEY = "example-test-rbac-http-key";
|
|
54
54
|
const ACTOR: IdentityActor = { kind: "operator", id: "test" };
|
|
55
55
|
|
|
56
56
|
async function removeDbFiles(path: string): Promise<void> {
|
|
@@ -20,7 +20,7 @@ import { getFreePort } from "./test-net";
|
|
|
20
20
|
export { getFreePort };
|
|
21
21
|
|
|
22
22
|
export const REPO_ROOT = join(import.meta.dir, "../..");
|
|
23
|
-
export const E2E_API_KEY = "rbac-e2e-key";
|
|
23
|
+
export const E2E_API_KEY = "example-rbac-e2e-key";
|
|
24
24
|
|
|
25
25
|
const SERVER_LOG_TAIL_BYTES = 8 * 1024;
|
|
26
26
|
|
|
@@ -81,6 +81,9 @@ const LEAD_ONLY_VERBS: PermissionVerb[] = [
|
|
|
81
81
|
"script.api.delete",
|
|
82
82
|
];
|
|
83
83
|
|
|
84
|
+
const OPERATOR_ONLY_VERBS: PermissionVerb[] = ["extension.activate"];
|
|
85
|
+
const LEAD_OR_OPERATOR_VERBS: PermissionVerb[] = ["extension.write"];
|
|
86
|
+
|
|
84
87
|
const LEAD_OR_RESOURCE_OWNER_VERBS: PermissionVerb[] = [
|
|
85
88
|
"memory.edit.any",
|
|
86
89
|
"skill.update.any",
|
|
@@ -171,6 +174,8 @@ describe("verb-group partition", () => {
|
|
|
171
174
|
...ANY_AUTHENTICATED_VERBS,
|
|
172
175
|
...REQUESTER_OWNS_TASK_VERBS,
|
|
173
176
|
...COMPOSITE_VERBS,
|
|
177
|
+
...OPERATOR_ONLY_VERBS,
|
|
178
|
+
...LEAD_OR_OPERATOR_VERBS,
|
|
174
179
|
];
|
|
175
180
|
expect(new Set(grouped).size).toBe(grouped.length);
|
|
176
181
|
expect(grouped.sort()).toEqual([...PERMISSION_VERBS].sort());
|
|
@@ -216,6 +221,40 @@ describe("lead-only verbs", () => {
|
|
|
216
221
|
});
|
|
217
222
|
});
|
|
218
223
|
|
|
224
|
+
describe("operator-or-user verbs", () => {
|
|
225
|
+
const expected: Expected = {
|
|
226
|
+
lead: false,
|
|
227
|
+
worker: false,
|
|
228
|
+
ownerWorker: false,
|
|
229
|
+
creatorWorker: false,
|
|
230
|
+
userRequester: true,
|
|
231
|
+
foreignUser: true,
|
|
232
|
+
operator: true,
|
|
233
|
+
};
|
|
234
|
+
for (const verb of OPERATOR_ONLY_VERBS) {
|
|
235
|
+
test(`${verb}: operator or user allowed`, () => {
|
|
236
|
+
expectDecisions(verb, { kind: "none" }, expected);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe("lead-or-operator-or-user verbs", () => {
|
|
242
|
+
const expected: Expected = {
|
|
243
|
+
lead: true,
|
|
244
|
+
worker: false,
|
|
245
|
+
ownerWorker: false,
|
|
246
|
+
creatorWorker: false,
|
|
247
|
+
userRequester: true,
|
|
248
|
+
foreignUser: true,
|
|
249
|
+
operator: true,
|
|
250
|
+
};
|
|
251
|
+
for (const verb of LEAD_OR_OPERATOR_VERBS) {
|
|
252
|
+
test(`${verb}: lead, operator, or user allowed`, () => {
|
|
253
|
+
expectDecisions(verb, { kind: "none" }, expected);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
219
258
|
describe("lead-or-resource-owner verbs", () => {
|
|
220
259
|
const expected: Expected = {
|
|
221
260
|
lead: true,
|
|
@@ -44,7 +44,7 @@ describe("realtime room namespace guards", () => {
|
|
|
44
44
|
|
|
45
45
|
test("allows page writes for user and operator contexts when RBAC is disabled", async () => {
|
|
46
46
|
const previous = process.env.RBAC_ENABLED;
|
|
47
|
-
|
|
47
|
+
process.env.RBAC_ENABLED = "false";
|
|
48
48
|
try {
|
|
49
49
|
await expect(
|
|
50
50
|
authorizeRoomNamespace(
|
|
@@ -23,7 +23,7 @@ import { registerRoomDecodeTool } from "../tools/rooms";
|
|
|
23
23
|
import { listenOnFreePort } from "./test-net";
|
|
24
24
|
|
|
25
25
|
const TEST_DB_PATH = "./test-realtime-room-surfaces.sqlite";
|
|
26
|
-
const API_KEY = "test-realtime-room-key";
|
|
26
|
+
const API_KEY = "example-test-realtime-room-key";
|
|
27
27
|
|
|
28
28
|
async function removeDbFiles(): Promise<void> {
|
|
29
29
|
for (const suffix of ["", "-wal", "-shm"]) {
|