@pikku/core 0.12.143 → 0.12.145
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/analytics/analytics.d.ts +14 -0
- package/dist/analytics/analytics.js +14 -0
- package/dist/analytics/analytics.types.d.ts +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +1 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +1 -0
- package/dist/analytics/mint-cookie.d.ts +1 -0
- package/dist/{wirings/channel/channel-middleware-runner.d.ts → channel-middleware-runner.d.ts} +17 -3
- package/dist/{wirings/channel/channel-middleware-runner.js → channel-middleware-runner.js} +24 -8
- package/dist/classification/data-classification.d.ts +13 -0
- package/dist/classification/secret-value.d.ts +7 -0
- package/dist/classification/secret-value.js +7 -0
- package/dist/crypto-utils.d.ts +93 -0
- package/dist/crypto-utils.js +92 -0
- package/dist/dev/hot-reload.d.ts +16 -0
- package/dist/dev/hot-reload.js +16 -1
- package/dist/dev/module-runner.js +7 -3
- package/dist/dev/reload-meta.js +1 -1
- package/dist/errors/error-handler.d.ts +9 -0
- package/dist/errors/error-handler.js +8 -0
- package/dist/errors/errors.d.ts +219 -0
- package/dist/errors/errors.js +227 -0
- package/dist/errors/serialized-error.d.ts +4 -0
- package/dist/function/abort-scope.d.ts +5 -0
- package/dist/function/function-meta.types.d.ts +20 -0
- package/dist/function/function-runner.d.ts +41 -0
- package/dist/function/function-runner.js +57 -11
- package/dist/function/functions.types.d.ts +59 -0
- package/dist/function/functions.types.js +23 -0
- package/dist/function/list.types.d.ts +4 -0
- package/dist/lifecycle.d.ts +12 -1
- package/dist/lifecycle.js +12 -1
- package/dist/middleware/addon-scope-cap.d.ts +4 -0
- package/dist/middleware/addon-scope-cap.js +7 -3
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.js +5 -13
- package/dist/middleware/auth-cookie.js +3 -3
- package/dist/middleware/middleware-factories.d.ts +17 -0
- package/dist/middleware/middleware-factories.js +17 -0
- package/dist/middleware/middleware.types.d.ts +23 -0
- package/dist/middleware/remote-auth.d.ts +15 -0
- package/dist/middleware/remote-auth.js +18 -3
- package/dist/middleware/remote-jobs-secret.js +2 -10
- package/dist/middleware-runner.d.ts +7 -0
- package/dist/middleware-runner.js +23 -7
- package/dist/permissions.d.ts +13 -0
- package/dist/permissions.js +13 -0
- package/dist/pikku-state.d.ts +49 -0
- package/dist/pikku-state.js +49 -0
- package/dist/remote.js +20 -5
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +36 -0
- package/dist/services/agent-run-state-service.d.ts +8 -0
- package/dist/services/agent-runner-service.d.ts +24 -0
- package/dist/services/agent-storage-service.d.ts +8 -0
- package/dist/services/ai-embedding-service.d.ts +4 -0
- package/dist/services/audit-service.d.ts +48 -0
- package/dist/services/audit-service.js +22 -0
- package/dist/services/content-service.d.ts +34 -0
- package/dist/services/credential-wire-service.d.ts +9 -0
- package/dist/services/credential-wire-service.js +9 -0
- package/dist/services/deployment-service.d.ts +14 -0
- package/dist/services/email-service.d.ts +20 -0
- package/dist/services/email-template.d.ts +24 -0
- package/dist/services/email-template.js +12 -0
- package/dist/services/file-scenario-run-store.d.ts +5 -0
- package/dist/services/file-scenario-run-store.js +4 -0
- package/dist/services/gateway-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.js +5 -0
- package/dist/services/in-memory-lease-service.d.ts +5 -0
- package/dist/services/in-memory-lease-service.js +5 -0
- package/dist/services/in-memory-session-store.d.ts +4 -0
- package/dist/services/in-memory-session-store.js +4 -0
- package/dist/services/incoming-webhook-queue.d.ts +2 -0
- package/dist/services/incoming-webhook-queue.js +2 -0
- package/dist/services/incoming-webhook-service.d.ts +9 -1
- package/dist/services/incoming-webhook-service.js +1 -1
- package/dist/services/index.d.ts +1 -5
- package/dist/services/index.js +1 -5
- package/dist/services/jwt-service.d.ts +8 -0
- package/dist/services/lease-service.d.ts +5 -0
- package/dist/services/lease-service.js +1 -0
- package/dist/services/local-content-request-handler.d.ts +20 -0
- package/dist/services/local-content-request-handler.js +11 -0
- package/dist/services/local-content.d.ts +45 -0
- package/dist/services/local-content.js +35 -0
- package/dist/services/local-credential-service.d.ts +5 -0
- package/dist/services/local-credential-service.js +5 -0
- package/dist/services/local-email-service.d.ts +7 -0
- package/dist/services/local-email-service.js +7 -0
- package/dist/services/local-secrets.d.ts +8 -0
- package/dist/services/local-secrets.js +8 -0
- package/dist/services/local-variables.d.ts +6 -0
- package/dist/services/local-variables.js +6 -0
- package/dist/services/logger.d.ts +4 -0
- package/dist/services/logger.js +4 -0
- package/dist/services/meta-service.d.ts +38 -0
- package/dist/services/meta-service.js +6 -0
- package/dist/services/queue-webhook-service.d.ts +19 -0
- package/dist/services/queue-webhook-service.js +19 -0
- package/dist/services/remote-jobs.d.ts +8 -13
- package/dist/services/remote-jobs.js +3 -54
- package/dist/services/scenario-cookie-jar.d.ts +4 -0
- package/dist/services/scheduler-service.d.ts +13 -0
- package/dist/services/scheduler-service.js +8 -0
- package/dist/services/schema-service.d.ts +9 -0
- package/dist/services/scope-service.d.ts +10 -0
- package/dist/services/scoped-secret-service.d.ts +5 -0
- package/dist/services/scoped-secret-service.js +5 -0
- package/dist/services/secret-host-binding.d.ts +5 -0
- package/dist/services/secret-host-binding.js +5 -0
- package/dist/services/secret-service.d.ts +19 -1
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +6 -0
- package/dist/services/session-store.d.ts +5 -0
- package/dist/services/stub-tracker.d.ts +1 -0
- package/dist/services/temporary-file-service.d.ts +9 -0
- package/dist/services/temporary-file-service.js +9 -0
- package/dist/services/trigger-service.d.ts +4 -0
- package/dist/services/trigger-source-store.d.ts +13 -0
- package/dist/services/trigger-source-store.js +7 -0
- package/dist/services/typed-credential-service.d.ts +6 -0
- package/dist/services/typed-credential-service.js +5 -0
- package/dist/services/typed-secret-service.d.ts +12 -0
- package/dist/services/typed-secret-service.js +11 -0
- package/dist/services/typed-variables-service.d.ts +1 -0
- package/dist/services/user-session-service.d.ts +31 -1
- package/dist/services/user-session-service.js +29 -3
- package/dist/services/v8-coverage-service.d.ts +27 -0
- package/dist/services/v8-coverage-service.js +5 -0
- package/dist/services/variables-service.d.ts +8 -0
- package/dist/services/virtual-user-sign-in.d.ts +1 -0
- package/dist/services/virtual-user-statement.d.ts +8 -0
- package/dist/services/virtual-user-statement.js +4 -0
- package/dist/services/webhook-service.d.ts +25 -0
- package/dist/services/webhook-service.js +15 -0
- package/dist/services/workflow-service.d.ts +6 -0
- package/dist/test-utils.js +1 -1
- package/dist/testing/service-tests.d.ts +4 -0
- package/dist/time-utils.d.ts +15 -0
- package/dist/time-utils.js +14 -0
- package/dist/types/core.types.d.ts +80 -0
- package/dist/types/state.types.d.ts +4 -0
- package/dist/utils/hmac.d.ts +3 -0
- package/dist/utils/safe-fetch.d.ts +14 -0
- package/dist/utils/safe-fetch.js +13 -0
- package/dist/utils/stable-stringify.d.ts +11 -0
- package/dist/utils/stable-stringify.js +33 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +22 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +7 -0
- package/dist/wirings/addon/define-screens.d.ts +2 -0
- package/dist/wirings/addon/remote-addon-auth.d.ts +9 -0
- package/dist/wirings/addon/remote-addon-auth.js +5 -0
- package/dist/wirings/addon/wire-addon.d.ts +4 -0
- package/dist/wirings/addon/wire-remote-addon.d.ts +1 -0
- package/dist/wirings/agent/agent-agui.d.ts +14 -5
- package/dist/wirings/agent/agent-agui.js +17 -6
- package/dist/wirings/agent/agent-helpers.d.ts +61 -1
- package/dist/wirings/agent/agent-helpers.js +62 -2
- package/dist/wirings/agent/agent-interrupt.d.ts +5 -0
- package/dist/wirings/agent/agent-output.d.ts +20 -0
- package/dist/wirings/agent/agent-output.js +69 -0
- package/dist/wirings/agent/agent-prepare.d.ts +41 -0
- package/dist/wirings/agent/agent-prepare.js +38 -2
- package/dist/wirings/agent/agent-registry.d.ts +8 -0
- package/dist/wirings/agent/agent-registry.js +10 -4
- package/dist/wirings/agent/agent-runner.d.ts +33 -0
- package/dist/wirings/agent/agent-runner.js +40 -7
- package/dist/wirings/agent/agent-stream.d.ts +30 -0
- package/dist/wirings/agent/agent-stream.js +33 -11
- package/dist/wirings/agent/agent.types.d.ts +43 -0
- package/dist/wirings/agent/voice-input.d.ts +12 -0
- package/dist/wirings/agent/voice-input.js +12 -0
- package/dist/wirings/agent/voice-output.d.ts +14 -0
- package/dist/wirings/agent/voice-output.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.js +1 -2
- package/dist/wirings/agent-scorer/agent-scorer-registry.d.ts +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.d.ts +1 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.js +1 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +7 -0
- package/dist/wirings/channel/channel-common.js +1 -1
- package/dist/wirings/channel/channel-rpc.types.d.ts +5 -0
- package/dist/wirings/channel/channel-runner.d.ts +22 -0
- package/dist/wirings/channel/channel-runner.js +22 -0
- package/dist/wirings/channel/channel-store.d.ts +8 -0
- package/dist/wirings/channel/channel-store.js +7 -0
- package/dist/wirings/channel/channel.types.d.ts +18 -0
- package/dist/wirings/channel/define-channel-routes.d.ts +5 -0
- package/dist/wirings/channel/define-channel-routes.js +5 -0
- package/dist/wirings/channel/eventhub-service.d.ts +9 -0
- package/dist/wirings/channel/eventhub-store.d.ts +1 -0
- package/dist/wirings/channel/eventhub-store.js +1 -0
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/index.js +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -0
- package/dist/wirings/channel/local/local-channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +13 -0
- package/dist/wirings/channel/local/local-channel-runner.js +13 -0
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +1 -0
- package/dist/wirings/channel/local/local-eventhub-service.js +1 -0
- package/dist/wirings/channel/log-channels.d.ts +1 -0
- package/dist/wirings/channel/log-channels.js +1 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +5 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +5 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +32 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +31 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +8 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +8 -0
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +43 -0
- package/dist/wirings/cli/cli-runner.js +43 -0
- package/dist/wirings/cli/cli.types.d.ts +4 -0
- package/dist/wirings/cli/command-parser.d.ts +13 -0
- package/dist/wirings/cli/command-parser.js +16 -0
- package/dist/wirings/credential/credential-overrides.d.ts +1 -0
- package/dist/wirings/credential/credential.types.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.js +7 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +1 -0
- package/dist/wirings/flag/flag.types.d.ts +3 -0
- package/dist/wirings/gateway/gateway-runner.d.ts +23 -0
- package/dist/wirings/gateway/gateway-runner.js +23 -0
- package/dist/wirings/gateway/gateway.types.d.ts +3 -0
- package/dist/wirings/gateway/local-gateway-service.d.ts +10 -0
- package/dist/{services → wirings/gateway}/local-gateway-service.js +6 -2
- package/dist/wirings/http/http-routes.d.ts +21 -0
- package/dist/wirings/http/http-routes.js +11 -0
- package/dist/wirings/http/http-runner.d.ts +71 -0
- package/dist/wirings/http/http-runner.js +73 -5
- package/dist/wirings/http/http.types.d.ts +27 -0
- package/dist/wirings/http/index.d.ts +1 -0
- package/dist/wirings/http/index.js +1 -0
- package/dist/wirings/http/log-http-routes.d.ts +1 -0
- package/dist/wirings/http/log-http-routes.js +1 -0
- package/dist/wirings/http/merge-request-data.d.ts +12 -0
- package/dist/wirings/http/merge-request-data.js +42 -0
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.js +3 -32
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +1 -0
- package/dist/wirings/http/routers/http-router.d.ts +6 -0
- package/dist/wirings/http/routers/http-router.js +6 -0
- package/dist/wirings/http/web-request.d.ts +17 -0
- package/dist/wirings/http/web-request.js +17 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +7 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.js +7 -0
- package/dist/wirings/mcp/mcp-runner.d.ts +63 -0
- package/dist/wirings/mcp/mcp-runner.js +62 -0
- package/dist/wirings/mcp/mcp.types.d.ts +12 -0
- package/dist/wirings/node/node.types.d.ts +4 -0
- package/dist/wirings/oauth2/oauth2.types.d.ts +2 -0
- package/dist/{services → wirings/queue}/in-memory-queue-service.d.ts +9 -1
- package/dist/{services → wirings/queue}/in-memory-queue-service.js +9 -1
- package/dist/wirings/queue/index.d.ts +1 -0
- package/dist/wirings/queue/index.js +1 -0
- package/dist/wirings/queue/queue-identity.js +2 -14
- package/dist/wirings/queue/queue-runner.d.ts +37 -0
- package/dist/wirings/queue/queue-runner.js +37 -0
- package/dist/wirings/queue/queue.types.d.ts +35 -0
- package/dist/wirings/queue/register-queue-helper.d.ts +12 -0
- package/dist/wirings/queue/register-queue-helper.js +11 -0
- package/dist/wirings/queue/remote-queue-job.d.ts +11 -0
- package/dist/wirings/queue/remote-queue-job.js +41 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -0
- package/dist/wirings/role/role.types.d.ts +3 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +24 -0
- package/dist/wirings/rpc/rpc-runner.js +37 -2
- package/dist/wirings/rpc/rpc-types.d.ts +2 -0
- package/dist/wirings/scheduler/index.d.ts +1 -0
- package/dist/wirings/scheduler/index.js +1 -0
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -0
- package/dist/wirings/scheduler/log-schedulers.js +1 -0
- package/dist/wirings/scheduler/remote-scheduled-job.d.ts +11 -0
- package/dist/wirings/scheduler/remote-scheduled-job.js +20 -0
- package/dist/wirings/scheduler/scheduler-runner.d.ts +29 -0
- package/dist/wirings/scheduler/scheduler-runner.js +28 -0
- package/dist/wirings/scheduler/scheduler.types.d.ts +3 -0
- package/dist/wirings/scope/scope.types.d.ts +5 -0
- package/dist/wirings/secret/index.d.ts +2 -2
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +26 -1
- package/dist/wirings/secret/secret.types.js +1 -0
- package/dist/wirings/secret/validate-secret-definitions.d.ts +8 -0
- package/dist/wirings/secret/validate-secret-definitions.js +15 -0
- package/dist/wirings/trigger/in-memory-trigger-service.d.ts +11 -0
- package/dist/{services → wirings/trigger}/in-memory-trigger-service.js +10 -3
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +8 -3
- package/dist/wirings/trigger/pikku-trigger-service.js +14 -3
- package/dist/wirings/trigger/trigger-runner.d.ts +27 -2
- package/dist/wirings/trigger/trigger-runner.js +35 -2
- package/dist/wirings/trigger/trigger.types.d.ts +26 -4
- package/dist/wirings/trigger/webhook-source-runner.d.ts +24 -0
- package/dist/wirings/trigger/webhook-source-runner.js +19 -0
- package/dist/wirings/trigger/webhook-source.types.d.ts +12 -2
- package/dist/wirings/trigger/webhook-source.types.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +7 -0
- package/dist/wirings/variable/validate-variable-definitions.js +7 -0
- package/dist/wirings/variable/variable.types.d.ts +7 -0
- package/dist/wirings/virtual-user/conversation/conversation.types.d.ts +5 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +6 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.js +1 -1
- package/dist/{services → wirings/virtual-user}/http-virtual-users.d.ts +4 -3
- package/dist/{services → wirings/virtual-user}/http-virtual-users.js +6 -6
- package/dist/wirings/virtual-user/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.js +1 -1
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +2 -1
- package/dist/wirings/virtual-user/run-virtual-user.js +1 -14
- package/dist/wirings/virtual-user/virtual-user-declaration.types.d.ts +4 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +10 -1
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.js +1 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +1 -0
- package/dist/wirings/webhook/define-outgoing-webhook.d.ts +20 -0
- package/dist/wirings/webhook/define-outgoing-webhook.js +9 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +8 -4
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +7 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +7 -0
- package/dist/wirings/workflow/feature.d.ts +12 -0
- package/dist/wirings/workflow/feature.js +12 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +5 -0
- package/dist/wirings/workflow/graph/graph-node.js +5 -0
- package/dist/wirings/workflow/graph/template.d.ts +6 -0
- package/dist/wirings/workflow/graph/template.js +5 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +12 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +10 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +11 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +1 -0
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.d.ts +8 -3
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.js +9 -4
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +1 -1
- package/dist/wirings/workflow/pikku-scenario-service.js +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +1 -0
- package/dist/wirings/workflow/pikku-workflow-service.js +1 -0
- package/dist/wirings/workflow/run-timeline.d.ts +21 -0
- package/dist/wirings/workflow/run-timeline.js +15 -7
- package/dist/wirings/workflow/scenario-coverage.d.ts +1 -0
- package/dist/wirings/workflow/scenario-poll.d.ts +1 -0
- package/dist/wirings/workflow/scenario-prose.d.ts +6 -0
- package/dist/wirings/workflow/scenario-prose.js +6 -0
- package/dist/wirings/workflow/scenario-run.types.d.ts +3 -0
- package/dist/wirings/workflow/scenario-step.types.d.ts +1 -0
- package/dist/wirings/workflow/scenario-step.types.js +1 -0
- package/dist/wirings/workflow/scenario-surface.js +1 -13
- package/dist/wirings/workflow/scenario.types.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +6 -0
- package/dist/wirings/workflow/workflow-constants.d.ts +7 -1
- package/dist/wirings/workflow/workflow-constants.js +10 -1
- package/dist/wirings/workflow/workflow-errors.d.ts +13 -0
- package/dist/wirings/workflow/workflow-errors.js +13 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +4 -0
- package/dist/wirings/workflow/workflow-invocation-id.js +4 -0
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +3 -0
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +1 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +1 -0
- package/dist/wirings/workflow/workflow-status-stream.d.ts +1 -0
- package/dist/wirings/workflow/workflow-unwind-plan.js +2 -7
- package/dist/wirings/workflow/workflow.types.d.ts +40 -0
- package/package.json +26 -9
- package/CHANGELOG.md +0 -6978
- package/dist/services/in-memory-trigger-service.d.ts +0 -4
- package/dist/services/local-gateway-service.d.ts +0 -6
- package/dist/utils/hash.d.ts +0 -2
- package/dist/utils/hash.js +0 -23
- package/knowledge/decisions/index.md +0 -19
- package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +0 -29
- package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +0 -29
- package/knowledge/decisions/internals/a-held-run-is-woken-later-not-retried.md +0 -28
- package/knowledge/decisions/internals/a-latency-budget-is-asserted-by-its-cause.md +0 -32
- package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-agentrunstate-too.md +0 -22
- package/knowledge/decisions/internals/a-reset-suite-makes-the-dev-seed-the-fixture.md +0 -50
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +0 -20
- package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +0 -21
- package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +0 -22
- package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +0 -28
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +0 -49
- package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +0 -32
- package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +0 -66
- package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +0 -24
- package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +0 -21
- package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +0 -34
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +0 -65
- package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +0 -49
- package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +0 -45
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +0 -26
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +0 -32
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +0 -33
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +0 -28
- package/knowledge/decisions/internals/agent-agui-bridge-obeys-the-client-ordering-contract.md +0 -29
- package/knowledge/decisions/internals/agent-audio-chunks-carry-the-format-the-provider-returned.md +0 -20
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +0 -21
- package/knowledge/decisions/internals/agent-credential-suspensions-hide-the-tool-result.md +0 -26
- package/knowledge/decisions/internals/agent-delegate-and-supervise-hide-different-text.md +0 -26
- package/knowledge/decisions/internals/agent-llm-tool-arguments-have-nulls-stripped.md +0 -23
- package/knowledge/decisions/internals/agent-model-config-stays-a-single-resolution-seam.md +0 -25
- package/knowledge/decisions/internals/agent-onerror-hooks-cannot-change-the-failure.md +0 -22
- package/knowledge/decisions/internals/agent-runner-methods-must-keep-their-receiver.md +0 -22
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +0 -22
- package/knowledge/decisions/internals/agent-stream-persistence-is-best-effort.md +0 -27
- package/knowledge/decisions/internals/agent-sub-agents-inherit-the-parent-context-block.md +0 -26
- package/knowledge/decisions/internals/agent-tool-execute-failures-are-logged-unconditionally.md +0 -25
- package/knowledge/decisions/internals/agent-voice-input-transcribes-audio-parts-in-place.md +0 -22
- package/knowledge/decisions/internals/agent-working-memory-is-persisted-only-when-valid.md +0 -25
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +0 -39
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +0 -23
- package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +0 -27
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +0 -25
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +0 -22
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +0 -20
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +0 -22
- package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +0 -26
- package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +0 -66
- package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +0 -22
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +0 -30
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +0 -31
- package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +0 -33
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +0 -29
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +0 -28
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +0 -27
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +0 -28
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +0 -34
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +0 -29
- package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +0 -84
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +0 -41
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +0 -44
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +0 -39
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +0 -42
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +0 -39
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +0 -43
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +0 -38
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +0 -44
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +0 -27
- package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +0 -22
- package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +0 -28
- package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +0 -24
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +0 -32
- package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +0 -43
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +0 -28
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +0 -31
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +0 -26
- package/knowledge/decisions/internals/global-middleware-resolves-from-the-root-namespace-too.md +0 -32
- package/knowledge/decisions/internals/hot-reload-reads-the-changed-source-never-a-compiled-copy.md +0 -38
- package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +0 -26
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +0 -32
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +0 -28
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +0 -30
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +0 -26
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +0 -28
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +0 -32
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +0 -26
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +0 -25
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +0 -26
- package/knowledge/decisions/internals/index.md +0 -182
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +0 -25
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +0 -26
- package/knowledge/decisions/internals/mcp-wire-names-are-assigned-over-the-whole-registry.md +0 -39
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +0 -24
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +0 -53
- package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +0 -21
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +0 -28
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +0 -27
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +0 -31
- package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +0 -30
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +0 -32
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +0 -31
- package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +0 -24
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +0 -26
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +0 -27
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +0 -48
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +0 -30
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +0 -28
- package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +0 -34
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +0 -24
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +0 -26
- package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +0 -43
- package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +0 -22
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +0 -30
- package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +0 -83
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +0 -29
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +0 -27
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +0 -40
- package/knowledge/decisions/internals/the-mcp-handshake-is-challenged-only-when-every-target-is-gated.md +0 -29
- package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +0 -40
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +0 -40
- package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +0 -24
- package/knowledge/decisions/internals/the-runner-resolves-wire-services-itself.md +0 -31
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +0 -26
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +0 -25
- package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +0 -21
- package/knowledge/decisions/internals/the-virtual-user-prompt-says-json-because-of-json-object-mode.md +0 -22
- package/knowledge/decisions/internals/the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md +0 -28
- package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +0 -22
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +0 -25
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +0 -33
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +0 -26
- package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +0 -43
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +0 -115
- package/knowledge/decisions/internals/virtual-user-conversation-drives-the-target-through-a-transport-seam.md +0 -24
- package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +0 -25
- package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +0 -23
- package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +0 -21
- package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +0 -30
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +0 -24
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +0 -26
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +0 -25
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +0 -58
- package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +0 -35
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +0 -34
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +0 -42
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +0 -38
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +0 -29
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +0 -42
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +0 -25
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +0 -29
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +0 -43
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +0 -29
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +0 -42
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +0 -33
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +0 -32
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +0 -31
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +0 -39
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +0 -29
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +0 -33
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +0 -37
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +0 -54
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +0 -43
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +0 -32
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +0 -18
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +0 -34
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +0 -29
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +0 -33
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +0 -34
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +0 -34
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +0 -38
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +0 -30
- package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +0 -26
- package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +0 -20
- package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +0 -23
- package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +0 -16
- package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +0 -26
- package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +0 -32
- package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +0 -27
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +0 -28
- package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +0 -33
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +0 -37
- package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +0 -33
- package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +0 -33
- package/knowledge/decisions/security/a-public-function-says-so-with-auth-false.md +0 -34
- package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +0 -25
- package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +0 -52
- package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +0 -27
- package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +0 -26
- package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +0 -25
- package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +0 -29
- package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +0 -25
- package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +0 -37
- package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +0 -24
- package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +0 -29
- package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +0 -30
- package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +0 -38
- package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +0 -23
- package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +0 -41
- package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +0 -25
- package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +0 -32
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +0 -50
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +0 -43
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +0 -52
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +0 -46
- package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +0 -20
- package/knowledge/decisions/security/agent-approval-forwarding-requires-a-symbol-brand.md +0 -27
- package/knowledge/decisions/security/agent-credential-requests-are-symbol-branded.md +0 -37
- package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +0 -31
- package/knowledge/decisions/security/agent-ownership-failures-never-echo-the-resource.md +0 -23
- package/knowledge/decisions/security/agent-resume-re-runs-the-authorization-gate.md +0 -22
- package/knowledge/decisions/security/agent-sessionless-deployments-have-no-thread-ownership.md +0 -39
- package/knowledge/decisions/security/agent-thread-ownership-composes-the-session-principal.md +0 -30
- package/knowledge/decisions/security/agent-tool-filtering-reads-the-live-function-config.md +0 -24
- package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +0 -26
- package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +0 -33
- package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +0 -16
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +0 -33
- package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +0 -26
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +0 -59
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +0 -30
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +0 -52
- package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +0 -38
- package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +0 -31
- package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +0 -18
- package/knowledge/decisions/security/an-mcp-refusal-is-decided-before-dispatch.md +0 -48
- package/knowledge/decisions/security/an-oauth2-credential-is-read-by-its-account-row.md +0 -40
- package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +0 -32
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +0 -24
- package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +0 -24
- package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +0 -26
- package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +0 -27
- package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +0 -25
- package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +0 -18
- package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +0 -29
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +0 -84
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +0 -39
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +0 -37
- package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +0 -22
- package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +0 -29
- package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +0 -27
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +0 -41
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +0 -30
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +0 -40
- package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +0 -25
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +0 -33
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +0 -46
- package/knowledge/decisions/security/index.md +0 -135
- package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +0 -21
- package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +0 -38
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +0 -27
- package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +0 -18
- package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +0 -22
- package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +0 -26
- package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +0 -24
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +0 -40
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +0 -31
- package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +0 -35
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +0 -69
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +0 -39
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +0 -34
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +0 -55
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +0 -30
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +0 -28
- package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +0 -31
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +0 -34
- package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +0 -22
- package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +0 -34
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +0 -37
- package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +0 -26
- package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +0 -24
- package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +0 -16
- package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +0 -21
- package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +0 -24
- package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +0 -34
- package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +0 -16
- package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +0 -29
- package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +0 -23
- package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +0 -25
- package/knowledge/decisions/security/virtual-user-conversation-missing-approval-decisions-default-to-denied.md +0 -22
- package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +0 -18
- package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +0 -25
- package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +0 -42
- package/knowledge/decisions/security/virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +0 -29
- package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +0 -29
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +0 -25
- package/knowledge/decisions/security/wire-addon-expose-selects-the-rpc-surface.md +0 -51
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +0 -40
- package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +0 -18
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +0 -31
- package/knowledge/decisions/security/workflow-virtual-user-steps-always-use-the-real-transport.md +0 -34
- package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +0 -18
- package/knowledge/index.md +0 -24
- package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +0 -24
- package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +0 -35
- package/knowledge/questions/dev-quick-login-as-impersonation.md +0 -25
- package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +0 -26
- package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +0 -27
- package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +0 -26
- package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +0 -26
- package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +0 -34
- package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +0 -20
- package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +0 -24
- package/knowledge/questions/does-the-store-session-match-the-other-two.md +0 -19
- package/knowledge/questions/index.md +0 -41
- package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +0 -21
- package/knowledge/questions/live-scheduled-tests-may-write.md +0 -19
- package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +0 -23
- package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +0 -32
- package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +0 -25
- package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +0 -23
- package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +0 -35
- package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +0 -23
- package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +0 -27
- package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +0 -26
- package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +0 -20
- package/knowledge/questions/staging-impersonation-rules.md +0 -27
- package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +0 -44
- package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +0 -33
- package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +0 -20
- package/knowledge/questions/what-an-impersonated-session-carries.md +0 -22
- package/run-tests.sh +0 -68
- package/scripts/generate-api-report.d.mts +0 -1
- package/scripts/generate-api-report.mjs +0 -96
- package/scripts/generate-api-report.mts +0 -333
- package/src/public-surface.json +0 -637
- package/src/public-surface.json.README +0 -43
- /package/dist/{function/compensation-name.d.ts → compensation-name.d.ts} +0 -0
- /package/dist/{function/compensation-name.js → compensation-name.js} +0 -0
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Virtual users are offered calls by declared scope, and approval-gated calls are denied by default
|
|
4
|
-
description: The catalogue type filters by the declared scopes of each RPC rather than by permission functions, and the catalogue filter drops approval-required entries unless the caller opts in
|
|
5
|
-
tags: core, virtual-users, scopes, approval
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Virtual users are offered calls by declared scope, and approval-gated calls are denied by default
|
|
9
|
-
|
|
10
|
-
`packages/core/src/wirings/virtual-user/virtual-user.types.ts` defines the
|
|
11
|
-
catalogue entry a virtual user is offered.
|
|
12
|
-
|
|
13
|
-
The `scopes` field lists the scopes the session must hold to call the RPC, all of
|
|
14
|
-
them (`virtual-user.types.ts:92-99`). The doc comment explains why scopes and not
|
|
15
|
-
permission functions: a scope is "declared and checkable", while "a permission is
|
|
16
|
-
arbitrary code whose verdict nobody can predict without running it"
|
|
17
|
-
(`virtual-user.types.ts:95-97`).
|
|
18
|
-
|
|
19
|
-
`approvalRequired` is documented as "denied by default" (`virtual-user.types.ts:89-90`).
|
|
20
|
-
The filter in `virtual-user-catalogue.ts` enforces this. It drops an entry when
|
|
21
|
-
`approvalRequired` is set and the caller has not passed `allowApprovalRequired`
|
|
22
|
-
(`virtual-user-catalogue.ts:113`), and that flag defaults to `false`
|
|
23
|
-
(`virtual-user-catalogue.ts:95`).
|
|
24
|
-
|
|
25
|
-
The same filter drops any entry the session's scopes do not cover
|
|
26
|
-
(`virtual-user-catalogue.ts:115-117`).
|
|
27
|
-
|
|
28
|
-
**What this rules out:** a virtual user calling an approval-gated RPC unless the
|
|
29
|
-
run explicitly allows it, and a permission function being used to decide what a
|
|
30
|
-
virtual user can see.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user's sign-in is refused unless the environment is known and allowed
|
|
4
|
-
description: Virtual user provisioning, sync and sign-in refuse when PIKKU_ENV is unresolved, unknown, production without the accountable disposition, or outside the virtual user's environments, and production environments are omitted by default
|
|
5
|
-
tags: core, virtual-users, environments, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user's sign-in is refused unless the environment is known and allowed
|
|
9
|
-
|
|
10
|
-
`virtualUserEnvironmentRefusal`
|
|
11
|
-
(`packages/core/src/wirings/virtual-user/virtual-user-environments.ts`) fails
|
|
12
|
-
closed when:
|
|
13
|
-
|
|
14
|
-
- `PIKKU_ENV` is unresolved;
|
|
15
|
-
- `PIKKU_ENV` names an environment the config does not know;
|
|
16
|
-
- the environment is production and the virtual user's disposition is not
|
|
17
|
-
`PRODUCTION_DISPOSITION` (`accountable`);
|
|
18
|
-
- the environment is not one the virtual user may target.
|
|
19
|
-
|
|
20
|
-
`resolveVirtualUserEnvironments` leaves production environments out when a
|
|
21
|
-
virtual user declares no `environments`. A virtual user reaches production only
|
|
22
|
-
when someone has named it there. The build-time half is
|
|
23
|
-
`virtualUserEnvironmentErrors`, which the doc comment says the inspector runs;
|
|
24
|
-
the run-time half is re-checked because "the run check does not trust which
|
|
25
|
-
artifact got deployed".
|
|
26
|
-
|
|
27
|
-
The refusal is applied by `pikku virtual-user sync`
|
|
28
|
-
(`packages/cli/src/functions/commands/virtual-user-sync.ts`), by the
|
|
29
|
-
`pikku virtual-user` command (`packages/cli/src/functions/commands/virtual-user.ts`)
|
|
30
|
-
and by `provisionVirtualUsers`
|
|
31
|
-
(`packages/services/better-auth/src/provision-virtual-users.ts`).
|
|
32
|
-
|
|
33
|
-
**What this rules out:** provisioning or signing in virtual users when the target
|
|
34
|
-
environment is ambiguous, and a production stage that carries virtual users it was
|
|
35
|
-
never meant to have.
|
|
36
|
-
|
|
37
|
-
Runs are stricter: [A virtual user never runs against production](a-virtual-user-never-runs-against-production.md)
|
|
38
|
-
refuses even the `accountable` disposition.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user is never offered a scenario, platform or addon step
|
|
4
|
-
description: Being able to invoke "the webhook arrives" lets the user manufacture the outcome it exists to discover, which invalidates every finding downstream
|
|
5
|
-
tags: core, virtual-user
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user is never offered a scenario, platform or addon step
|
|
9
|
-
|
|
10
|
-
`deriveVirtualUserCatalogue` excludes scenario bodies and their steps, and
|
|
11
|
-
platform and addon steps, from what a virtual user may call.
|
|
12
|
-
|
|
13
|
-
For scenario bodies the argument is only efficiency: they are held out of every
|
|
14
|
-
deployed unit and are not network-callable, so offering one wastes a turn on a 404.
|
|
15
|
-
|
|
16
|
-
For a platform or addon step the argument is the oracle itself. A virtual user's
|
|
17
|
-
findings are worth something _because_ it cannot manufacture the outcomes it is
|
|
18
|
-
meant to discover. A user that could invoke "Stripe's webhook arrives" forges its
|
|
19
|
-
own payment success, and every finding downstream of that forgery is worthless —
|
|
20
|
-
not merely unreliable, but actively misleading, because it looks like evidence.
|
|
21
|
-
|
|
22
|
-
This is the same class of argument as `allowApprovalRequired` defaulting to
|
|
23
|
-
false, and it is enforced here at derivation rather than left to convention.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** exposing platform steps behind a flag "for
|
|
26
|
-
convenience", or filtering them later in the run loop where a caller could skip
|
|
27
|
-
the filter.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user never runs against production, whatever its disposition
|
|
4
|
-
description: startVirtualUserRun and an enabling writeVirtualUserSchedule both refuse with a 403 in production, including for the accountable disposition; an unresolved environment counts as production
|
|
5
|
-
tags: core, virtual-users, environments, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user never runs against production, whatever its disposition
|
|
9
|
-
|
|
10
|
-
`refuseInProduction` (`packages/core/src/wirings/virtual-user/virtual-user-scaffold.ts:192`) throws a `ForbiddenError`, "Virtual users do not run against production", whenever the process is a production run. It has no disposition exception: `accountable`, which the virtual user environment check still accepts at sign-in in production, is refused here too.
|
|
11
|
-
|
|
12
|
-
It is called from two places:
|
|
13
|
-
|
|
14
|
-
- `startVirtualUserRun` (`virtual-user-scaffold.ts:232`), before the run record is created, so a refused run leaves no row.
|
|
15
|
-
- `writeVirtualUserSchedule` (`virtual-user-scaffold.ts:410`), only when the row is or becomes enabled. Disabling a schedule, or editing one that is off, is still allowed in production so a leftover schedule can be stopped. A scheduled tick dispatches `runVirtualUser` through `rpc.invoke` (`packages/cli/src/functions/wirings/virtual-user/serialize-virtual-user-functions.ts:563-566`), and that function calls `startVirtualUserRun` (same file, line 337), so a due tick is refused as well.
|
|
16
|
-
|
|
17
|
-
"Production" is decided by `isProductionRun` (`virtual-user-scaffold.ts:179`). The configured `PIKKU_ENV` environment wins when the project configures environments, and an unresolved environment counts as production. `NODE_ENV` decides only for a project that configures none.
|
|
18
|
-
|
|
19
|
-
The sign-in environment rule is separate and unchanged. See [A virtual user's sign-in is refused unless the environment is known and allowed](a-virtual-user-environment-fails-closed.md): signing an `accountable` virtual user in against production is still allowed there, and starting a run is not.
|
|
20
|
-
|
|
21
|
-
The tests are in `virtual-user-scaffold.test.ts`: "refuses every disposition in production", "the accountable disposition is refused in production too", "an accountable cadence is refused in production too" and "disabling or editing an off cadence is allowed in production".
|
|
22
|
-
|
|
23
|
-
**What this rules out:** a virtual user, probing or not, acting on real customers' data, and an enabled schedule that can only ever fail to start in production.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user reads its roles from the app's own RPC before better-auth's user.role
|
|
4
|
-
description: sessionRoles asks getMyScopes first, then get-session, and returns null rather than an empty list when the stage reports no roles
|
|
5
|
-
tags: core, virtual-users, auth
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user reads its roles from the app's own RPC before better-auth's user.role
|
|
9
|
-
|
|
10
|
-
`HttpVirtualUser.sessionRoles` (`packages/core/src/services/http-virtual-users.ts`) answers
|
|
11
|
-
"what roles does this session hold" in a fixed order. First the app's exposed RPC,
|
|
12
|
-
which defaults to `getMyScopes` and can be renamed or switched off with `rolesRpc`.
|
|
13
|
-
Only then better-auth's `get-session`, where its admin plugin puts `role` on the
|
|
14
|
-
user.
|
|
15
|
-
|
|
16
|
-
The `rolesRpc` doc comment gives the reason. In an app that authorizes on scopes,
|
|
17
|
-
`user.role` is "a projection rather than the model": it exists so better-auth's
|
|
18
|
-
admin endpoints have something to read, and it may be absent. A virtual user verified
|
|
19
|
-
against it is verified against a copy.
|
|
20
|
-
|
|
21
|
-
Two answers are kept apart. A stage that answers neither returns `null`, which
|
|
22
|
-
means "this stage does not report roles". A session that carries a user with no
|
|
23
|
-
role field returns `[]`, which means "this person has none". The doc comment says
|
|
24
|
-
the two call for opposite responses from the caller.
|
|
25
|
-
|
|
26
|
-
**What this rules out:** making better-auth's `user.role` the first source of a
|
|
27
|
-
virtual user's roles, and reporting `[]` for a stage that could not answer at all.
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual-user run treats an unresolved PIKKU_ENV as production
|
|
4
|
-
description: The virtual-user scaffold decides "production" from the configured PIKKU_ENV environment, counts an unresolved one as production, and falls back to NODE_ENV only when no environments are configured
|
|
5
|
-
tags: core, virtual-users, environments, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual-user run treats an unresolved PIKKU_ENV as production
|
|
9
|
-
|
|
10
|
-
`startVirtualUserRun` calls `refuseInProduction` before it creates a run record
|
|
11
|
-
(`packages/core/src/wirings/virtual-user/virtual-user-scaffold.ts:232`). `PIKKU_ENV`
|
|
12
|
-
is read as the default for `environment` (`virtual-user-scaffold.ts:217`). The
|
|
13
|
-
schedule writer runs the same check when the schedule is or becomes enabled
|
|
14
|
-
(`virtual-user-scaffold.ts:399`, `:409-411`).
|
|
15
|
-
|
|
16
|
-
`refuseInProduction` throws a `ForbiddenError` whenever `isProductionRun` is true,
|
|
17
|
-
whatever the disposition (`virtual-user-scaffold.ts:192-204`). That rule is
|
|
18
|
-
[a virtual user never runs against production](a-virtual-user-never-runs-against-production.md);
|
|
19
|
-
this note is about how "production" is decided.
|
|
20
|
-
|
|
21
|
-
`isProductionRun` decides it as follows (`virtual-user-scaffold.ts:179-188`):
|
|
22
|
-
|
|
23
|
-
- With no environments configured, it is `NODE_ENV === 'production'` (`:184-186`).
|
|
24
|
-
- With environments configured and `PIKKU_ENV` unset, it is true (`:187`,
|
|
25
|
-
`environment ? ... : true`).
|
|
26
|
-
- With `PIKKU_ENV` set, it is that environment's `production` flag (`:187`). An
|
|
27
|
-
unknown name evaluates to false in this check. `virtualUserEnvironmentRefusal`
|
|
28
|
-
refuses unknown names at sign-in instead
|
|
29
|
-
(`packages/core/src/wirings/virtual-user/virtual-user-environments.ts:113-119`).
|
|
30
|
-
|
|
31
|
-
The comment gives the reasons. The configured environment wins over `NODE_ENV`
|
|
32
|
-
because a production mirror runs `NODE_ENV=production` too
|
|
33
|
-
(`virtual-user-scaffold.ts:166-172`). An unresolved environment counts as
|
|
34
|
-
production because nobody can vouch for its data (`:174-177`).
|
|
35
|
-
|
|
36
|
-
See also [a virtual user's sign-in is refused unless the environment is known and allowed](a-virtual-user-environment-fails-closed.md),
|
|
37
|
-
which covers the sign-in refusal in `virtual-user-environments.ts`.
|
|
38
|
-
|
|
39
|
-
**What this rules out:** starting a run when the environment cannot be named, and
|
|
40
|
-
keying the scaffold's refusal on `NODE_ENV` in a project that has configured
|
|
41
|
-
environments.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user's scopes are expanded from its roles once, at run preparation
|
|
4
|
-
description: A virtual user's scope set is computed from its declared roles against the defineSystemRole definitions when the run is prepared, and that set is the oracle for scope drift
|
|
5
|
-
tags: core, virtual-user, auth
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user's scopes are expanded from its roles once, at run preparation
|
|
9
|
-
|
|
10
|
-
`virtualUserScopes` in `packages/core/src/wirings/virtual-user/prepare-virtual-user-run.ts`
|
|
11
|
-
expands a virtual user's `roles` into scopes through the role definitions the seed
|
|
12
|
-
grants from. Its doc comment says roles are the only thing a virtual user declares, and
|
|
13
|
-
that the expansion happens "once, here, against the same `defineSystemRole`
|
|
14
|
-
definitions the seed grants from".
|
|
15
|
-
|
|
16
|
-
The result feeds two things in `run-virtual-user.ts`. It narrows the catalogue
|
|
17
|
-
for a non-adversarial user, and it is the oracle: a call that succeeds on an
|
|
18
|
-
endpoint whose `scopes` the virtual user does not hold is recorded as
|
|
19
|
-
`unexpected-success`, which the code calls authorization drift. Using the static
|
|
20
|
-
expansion as the truth is what makes that finding mean something, because the
|
|
21
|
-
run never asks the target what the virtual user may do.
|
|
22
|
-
|
|
23
|
-
**What this rules out:** building a virtual user's catalogue or judging its
|
|
24
|
-
successes from a scope list fetched from the live session, which would make the
|
|
25
|
-
oracle agree with whatever the target currently grants.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A virtual user whose granted roles drift from its declaration refuses to run
|
|
4
|
-
description: verifyVirtualUserRoles compares declared and granted roles in both directions before a run, and roleMismatchMessage produces the refusal text; a provider login is never runnable
|
|
5
|
-
tags: core, virtual-users, roles, drift
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A virtual user whose granted roles drift from its declaration refuses to run
|
|
9
|
-
|
|
10
|
-
`packages/core/src/wirings/virtual-user/validate-virtual-users.ts` has the role check that
|
|
11
|
-
runs before a virtual user's first step. `verifyVirtualUserRoles` computes what is missing
|
|
12
|
-
and what is extra, in both directions (`validate-virtual-users.ts:94-111`). `roleMismatchMessage`
|
|
13
|
-
returns `null` when they match, and otherwise a message that ends with "Refusing
|
|
14
|
-
to run" (`validate-virtual-users.ts:114-133`, the text at `validate-virtual-users.ts:131`).
|
|
15
|
-
|
|
16
|
-
The doc comment says the declaration is authoritative, but a run may target a
|
|
17
|
-
stage that the generated seed never touched (`validate-virtual-users.ts:84-87`). It
|
|
18
|
-
gives a reason for each direction: an under-granted virtual user reports seed drift
|
|
19
|
-
as an authorization bug, and an over-granted one "silently stops testing the
|
|
20
|
-
boundary it was written to test" (`validate-virtual-users.ts:89-92`).
|
|
21
|
-
|
|
22
|
-
Nothing in `packages/core/src` calls `roleMismatchMessage`. The caller that
|
|
23
|
-
stops the run is the `pikku virtual-user` command
|
|
24
|
-
(`packages/cli/src/functions/commands/virtual-user.ts`), so this file only
|
|
25
|
-
supplies the check and the message.
|
|
26
|
-
|
|
27
|
-
`isRunnableVirtualUser` (`validate-virtual-users.ts:19-27`) returns false for a virtual user
|
|
28
|
-
with `runnable: false`, and for any virtual user with an account provider, because
|
|
29
|
-
driving a provider consent screen "needs a human" (`validate-virtual-users.ts:10-12`).
|
|
30
|
-
|
|
31
|
-
**What this rules out:** running a virtual user whose roles no longer match what
|
|
32
|
-
it declared, and a provider-login virtual user being driven by a run.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A workflow run is read by its owner, and answered by whoever its gate declares
|
|
4
|
-
description: A run started through a session records that user and only that user may read it; who may answer an approval gate is the gate's own declaration, and a run with no recorded owner has no ownership to enforce
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A workflow run is read by its owner, and answered by whoever its gate declares
|
|
9
|
-
|
|
10
|
-
`WorkflowRunWire.pikkuUserId` has always been recorded on every run started
|
|
11
|
-
through a session — `RPCService.startWorkflow` copies it off the wire — and
|
|
12
|
-
nothing read it back. Run ids were the only secret protecting both the status
|
|
13
|
-
routes (which stream `output` and `error`) and `approveStep`, which took no
|
|
14
|
-
session at all and rejected only an already-resolved gate.
|
|
15
|
-
|
|
16
|
-
`assertWorkflowRunOwner`
|
|
17
|
-
(`packages/core/src/wirings/workflow/workflow-run-ownership.ts`) is the check the
|
|
18
|
-
**read** paths share: the generated status routes assert it against the run they
|
|
19
|
-
were already reading.
|
|
20
|
-
|
|
21
|
-
**A run with no recorded owner is not gated.** Triggers, schedulers and routes
|
|
22
|
-
wired without auth start runs with no `pikkuUserId`; there is nobody to compare a
|
|
23
|
-
caller against, and inventing one would reject the framework's own callers rather
|
|
24
|
-
than secure anything. Gate those at the entrypoint with `auth` or `permissions`.
|
|
25
|
-
|
|
26
|
-
This is ownership, not an approver model. It answers "is this your run", not "are
|
|
27
|
-
you entitled to approve this particular gate".
|
|
28
|
-
|
|
29
|
-
## Approving is a separate question, and the gate answers it
|
|
30
|
-
|
|
31
|
-
`approveStep` originally shared `assertWorkflowRunOwner`, which made "only the
|
|
32
|
-
initiator may answer" the one available rule. That is right for "confirm your own
|
|
33
|
-
action" and exactly wrong for four-eyes sign-off, where the initiator is the one
|
|
34
|
-
person who must not sign. Which applies is a property of the decision, so it is
|
|
35
|
-
declared on the gate — `approvers` (`'any' | 'owner' | 'not-initiator'`) and
|
|
36
|
-
`approverScope` on `WorkflowApprovalOptions`.
|
|
37
|
-
|
|
38
|
-
It is enforced wherever the policy is known. Reaching the gate publishes the
|
|
39
|
-
policy into the run state, so a decision submitted after that is judged by the
|
|
40
|
-
approve entrypoint and refused with a 403. A decision can legitimately be
|
|
41
|
-
recorded before the run has reached the gate, and that one has no policy to be
|
|
42
|
-
judged against yet — it is judged on replay instead, alongside payload
|
|
43
|
-
validation, and discarded if it fails.
|
|
44
|
-
|
|
45
|
-
The default is therefore `any`: a gate is a pause for a decision, not an
|
|
46
|
-
authorization boundary, and a route that needs one has `auth`/`permissions`.
|
|
47
|
-
|
|
48
|
-
**What this rules out:** treating a run id as a capability, adding a new run read
|
|
49
|
-
path that does not take a session, and re-deriving who may approve from who
|
|
50
|
-
started the run.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Addon auth and tags only tighten, and resolve where the function runs
|
|
4
|
-
description: wireAddon auth and tags are applied in runPikkuFunc like scopes, but auth:false is ignored and tags resolve against the consuming app's tag groups rather than the addon package's
|
|
5
|
-
tags: addon, auth, tags, authorization
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Addon auth and tags only tighten, and resolve where the function runs
|
|
9
|
-
|
|
10
|
-
`wireAddon({ auth, tags })` was read only by `resolveAddonFunction` in
|
|
11
|
-
`rpc-runner.ts`, which covers the `namespace:function` RPC form alone. Every
|
|
12
|
-
direct wiring — the inspector writes the addon's package name onto http,
|
|
13
|
-
channel, schedule, queue, cli, trigger, gateway and mcp wirings — reached
|
|
14
|
-
`runPikkuFunc` with a `packageName` and neither value. That is the same hole
|
|
15
|
-
[addon scopes](./addon-scopes-are-resolved-where-the-function-runs.md) had, and
|
|
16
|
-
it is closed the same way: `runPikkuFunc` resolves both from the addon config.
|
|
17
|
-
|
|
18
|
-
`auth` merges as an OR and `auth: false` is ignored. The RPC path treats it as a
|
|
19
|
-
default (`addonConfig?.auth ?? options.requiresAuth`) because there the addon
|
|
20
|
-
config is the only statement of intent. On a direct wiring the route already
|
|
21
|
-
carries its own `auth`, so honouring `false` would let an addon _weaken_ a gate
|
|
22
|
-
the app wrote — the inverse of what a wiring-level declaration should be able to
|
|
23
|
-
do. An addon may require a session the wiring did not; it may never waive one
|
|
24
|
-
the wiring did.
|
|
25
|
-
|
|
26
|
-
Tags resolve against the **root** tag groups, not the addon package's. A tag on
|
|
27
|
-
`wireAddon` is written by the consuming app, and `addTagMiddleware('admin', …)`
|
|
28
|
-
in that app registers under the root package. `combineMiddleware` looks tag
|
|
29
|
-
metadata up under the `packageName` it is given, which for an addon function is
|
|
30
|
-
the addon's own namespace — where the app's middleware does not exist. Resolving
|
|
31
|
-
addon tags to concrete middleware before the call and passing them as
|
|
32
|
-
`wireMiddleware` is what keeps `wireAddon({ tags: ['admin'] })` from being
|
|
33
|
-
silently inert, which is the failure mode the whole gate exists to avoid.
|
|
34
|
-
|
|
35
|
-
A function's own tags are unaffected: the inspector already emits them as
|
|
36
|
-
`{ type: 'tag' }` entries on the function and wiring meta, resolved under the
|
|
37
|
-
package that declared them. The `tags` argument `runPikkuFunc` accepts is
|
|
38
|
-
separate and still unused on every path.
|
|
39
|
-
|
|
40
|
-
**What this rules out:** honouring `auth: false` from an addon on a direct
|
|
41
|
-
wiring; resolving addon tags under the addon's `packageName`; and folding addon
|
|
42
|
-
tags into `funcInheritedMiddleware`, which would resolve them in the wrong
|
|
43
|
-
namespace and double-apply the function's own tags.
|
package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Addon auth and tag gates apply wherever the function runs, including inside the addon
|
|
4
|
-
description: wireAddon's auth and tags moved from the namespaced RPC boundary into runPikkuFunc, so they also apply to direct wirings and to bare intra-addon calls
|
|
5
|
-
tags: rpc, addon, auth
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Addon auth and tag gates apply wherever the function runs, including inside the addon
|
|
9
|
-
|
|
10
|
-
`ContextAwareRPCService.invokeAddonFunction` used to be the only place that
|
|
11
|
-
applied an addon's `addonConfig.auth` and `addonConfig.tags`, making them a
|
|
12
|
-
perimeter control on `rpc('namespace:fn')`. That perimeter had a hole in it: the
|
|
13
|
-
inspector writes the addon's package name onto http, channel, schedule, queue,
|
|
14
|
-
cli, trigger, gateway and mcp wirings, and every one of those runners calls
|
|
15
|
-
`runPikkuFunc` directly without resolving a namespace. A consumer who wrote
|
|
16
|
-
`wireAddon({ auth: true })` and then wired an addon function to a route got no
|
|
17
|
-
gate at all.
|
|
18
|
-
|
|
19
|
-
Both values now resolve in `runPikkuFunc`, the one point every path shares —
|
|
20
|
-
the same move, for the same reason, as
|
|
21
|
-
[addon scopes](./addon-scopes-are-resolved-where-the-function-runs.md). See
|
|
22
|
-
[addon auth and tags only tighten](./addon-auth-and-tags-only-tighten.md) for
|
|
23
|
-
the merge rules.
|
|
24
|
-
|
|
25
|
-
This replaces a consequence an earlier decision accepted: a bare `rpc('fn')`
|
|
26
|
-
made from inside an addon now re-applies the gate, because it reaches
|
|
27
|
-
`runPikkuFunc` with the addon's `packageName` like any other call. The earlier
|
|
28
|
-
reasoning — that the perimeter had already been passed, so re-checking would
|
|
29
|
-
gate internal calls on a consumer-facing setting — held only while the perimeter
|
|
30
|
-
was real. Once a direct wiring could enter the addon without passing any gate,
|
|
31
|
-
"already inside" stopped being something the runtime could infer, and the choice
|
|
32
|
-
became re-checking or trusting an entry that may never have happened.
|
|
33
|
-
|
|
34
|
-
In practice an intra-addon call inherits the entry point's session, so the auth
|
|
35
|
-
check passes wherever the entry was itself authenticated. What it does break is
|
|
36
|
-
an addon that wires `auth: true` and also runs its own sessionless internal
|
|
37
|
-
work — a scheduled task or queue worker inside the addon calling a sibling. Such
|
|
38
|
-
an addon should carry authorization on the function via
|
|
39
|
-
`pikkuFunc({ permissions })`, which has always been enforced on every path,
|
|
40
|
-
rather than on the consumer-facing `wireAddon` setting.
|
|
41
|
-
|
|
42
|
-
Re-checking was chosen over provenance because the marker that would make
|
|
43
|
-
"already inside" knowable — set by the runtime, unsettable by any caller outside
|
|
44
|
-
the process, threaded through all eight runners — is a design problem of its
|
|
45
|
-
own, and shipping it inside a security fix would have meant landing an untested
|
|
46
|
-
trust signal alongside the gate that depends on it. Adding that marker is
|
|
47
|
-
tracked separately; until it exists, re-checking is the only option that does
|
|
48
|
-
not trust an entry which may never have happened.
|
|
49
|
-
|
|
50
|
-
**What this rules out:** treating `addonConfig.auth` as a perimeter-only
|
|
51
|
-
control; and inferring "already inside the addon" from the wire, which a direct
|
|
52
|
-
wiring does not set.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Addon scopes are resolved where the function runs
|
|
4
|
-
description: wireAddon scopes are merged inside runPikkuFunc rather than at namespace resolution, because most wirings reach an addon function without ever resolving a namespace
|
|
5
|
-
tags: addon, scopes, authorization
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Addon scopes are resolved where the function runs
|
|
9
|
-
|
|
10
|
-
`wireAddon({ scopes })` names scopes every function in the addon's package
|
|
11
|
-
requires. `runPikkuFunc` calls `resolveAddonScopes(packageName,
|
|
12
|
-
addonInstance?.namespace)` and unions the result with the function's own
|
|
13
|
-
`scopes` before `verifyScopes`.
|
|
14
|
-
|
|
15
|
-
The obvious home for this is `resolveAddonFunction` in `rpc-runner.ts`, next to
|
|
16
|
-
where `auth` and `tags` are already merged from the addon config — but that
|
|
17
|
-
covers only the `namespace:function` RPC form. An addon function is reachable
|
|
18
|
-
without any namespace resolution: the inspector's `resolveAddonName` writes the
|
|
19
|
-
addon's package name onto the wiring meta whenever a wiring's `func` is an
|
|
20
|
-
identifier imported from a wired addon, and every runner (`http-runner`,
|
|
21
|
-
`mcp-runner`, channel, scheduler, queue, cli, trigger, gateway) then passes that
|
|
22
|
-
`packageName` straight to `runPikkuFunc`. `refHTTP` / `refChannel` / `refCLI`
|
|
23
|
-
contracts do the same through `registerHTTPRouteMeta`. A gate at namespace
|
|
24
|
-
resolution would leave every one of those doors open while reading as complete,
|
|
25
|
-
which is worse than no gate. `runPikkuFunc` is the one point all of them share.
|
|
26
|
-
|
|
27
|
-
Merging is a union, not an override, because `firstUnsatisfied` in `scopes.ts`
|
|
28
|
-
requires every listed scope. An addon scope is therefore an additional
|
|
29
|
-
requirement and can only narrow access — an addon can never weaken a function
|
|
30
|
-
that declares stricter scopes of its own. `ref('namespace:fn')` routes are
|
|
31
|
-
gated for the same reason from the other direction: the generated wrapper is a
|
|
32
|
-
local function that calls `rpc.invoke`, so the addon's scopes attach on the
|
|
33
|
-
inner call rather than the route.
|
|
34
|
-
|
|
35
|
-
When the caller carries an `addonInstance`, its namespace selects that
|
|
36
|
-
instance's scopes exactly. The direct-wiring paths know only a package name, so
|
|
37
|
-
`resolveAddonScopes` unions the scopes of every namespace the package is wired
|
|
38
|
-
under. One package wired twice with different scopes is rare; taking the
|
|
39
|
-
stricter reading keeps the unnamed path from becoming the weak one.
|
|
40
|
-
|
|
41
|
-
**What this rules out:** gating addon functions in `resolveAddonFunction`,
|
|
42
|
-
`resolveNamespace`, or any per-wiring runner; treating addon scopes as a
|
|
43
|
-
default that a function's own `scopes` replaces; resolving a package's scopes
|
|
44
|
-
by first matching namespace, the way `findAddonNamespaceForPackage` resolves
|
|
45
|
-
services; and reusing this for `wireRemoteAddon`, whose functions execute on the
|
|
46
|
-
host and are gated there.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Addon screen scopes hide a screen and do not enforce access
|
|
4
|
-
description: The scopes on a defineScreens entry state what a viewer must hold to see the screen; the addon's own functions are the access check
|
|
5
|
-
tags: core, addons, screens, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Addon screen scopes hide a screen and do not enforce access
|
|
9
|
-
|
|
10
|
-
`packages/core/src/wirings/addon/define-screens.ts:7-8` documents `scopes` on an
|
|
11
|
-
addon screen as required of the viewer to see it, and says the addon's functions
|
|
12
|
-
must enforce the same scopes, because hiding a screen is not access control.
|
|
13
|
-
|
|
14
|
-
The field is read statically by `pikku all`, which is why `scopes` must be a
|
|
15
|
-
literal (`define-screens.ts:32`). Within `packages/core/src`, no code reads a
|
|
16
|
-
screen's `scopes` at runtime; `wire-addon.ts:47-48` mounts the screens under
|
|
17
|
-
`/addons/<name>` and is the only other place they are referenced.
|
|
18
|
-
|
|
19
|
-
**What this rules out:** relying on a screen's scopes to keep data from a viewer,
|
|
20
|
-
and an addon shipping a function that trusts the screen to have been hidden.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Only a Symbol-branded framework result can request tool approval
|
|
4
|
-
description: Approval markers are trusted from the APPROVAL_REQUIRED Symbol on a forwardsApproval tool, never from a JSON key an LLM could emit
|
|
5
|
-
tags: agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Only a Symbol-branded framework result can request tool approval
|
|
9
|
-
|
|
10
|
-
`checkForApprovals` in
|
|
11
|
-
`packages/core/src/wirings/agent/agent-stream.ts` honours a forwarded
|
|
12
|
-
approval only when both hold: the tool declares `forwardsApproval` (set solely by
|
|
13
|
-
framework code on the sub-agent delegating tools built in
|
|
14
|
-
`agent-prepare.ts`), and its result carries the `APPROVAL_REQUIRED` unique
|
|
15
|
-
Symbol. The companion `__approvalRequired` string key exists for transport, but
|
|
16
|
-
is never what the decision reads.
|
|
17
|
-
|
|
18
|
-
A tool result is attacker-influenceable — a retrieved document, a third-party API
|
|
19
|
-
response, or a sub-agent's LLM-shaped `result.object`. All of those are plain
|
|
20
|
-
JSON, and plain JSON cannot carry a Symbol. Trusting the string key would let any
|
|
21
|
-
ordinary tool conjure a suspension and an approval prompt showing a tool name and
|
|
22
|
-
arguments of its choosing.
|
|
23
|
-
|
|
24
|
-
**What this rules out:** checking `'__approvalRequired' in result` as the
|
|
25
|
-
condition; replacing the Symbol with a string or numeric sentinel so results
|
|
26
|
-
survive JSON serialization; and setting `forwardsApproval` from user-supplied
|
|
27
|
-
tool configuration rather than from framework code.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Credential requests are trusted only when Symbol-branded
|
|
4
|
-
description: The string key is a wire field; the Symbol is the capability, and only core can mint it
|
|
5
|
-
tags: agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Credential requests are trusted only when Symbol-branded
|
|
9
|
-
|
|
10
|
-
A tool result asking the run to suspend and prompt for a credential is honoured
|
|
11
|
-
only when it carries the `CREDENTIAL_REQUIRED` Symbol minted in
|
|
12
|
-
`agent-prepare.ts`. `checkForCredentialRequests` in `agent-stream.ts`
|
|
13
|
-
tests for that Symbol, never for the `__credentialRequired` string key that
|
|
14
|
-
travels beside it on the wire.
|
|
15
|
-
|
|
16
|
-
The distinction is the whole security property. Tool results are frequently
|
|
17
|
-
attacker-influenceable — a retrieved document, an echo from a third-party API,
|
|
18
|
-
LLM-authored content round-tripping through a tool — and any of those can carry
|
|
19
|
-
a string key. None can carry a Symbol, because a Symbol has no literal form and
|
|
20
|
-
does not survive JSON. Without the brand, an influenced tool result could
|
|
21
|
-
suspend the run and push a `credential-request` event with an attacker-chosen
|
|
22
|
-
`connectUrl`, which the client renders as a "Connect" button: a phishing
|
|
23
|
-
primitive inside the product's own UI. This mirrors the `APPROVAL_REQUIRED`
|
|
24
|
-
brand, which exists for the identical reason one function over.
|
|
25
|
-
|
|
26
|
-
The brand survives because the object is passed by reference the whole way —
|
|
27
|
-
core's `buildToolDefs` wrapper returns it, the Vercel adapter's `agentTool` hands
|
|
28
|
-
it back verbatim, and the AI SDK puts the raw value on the stream part rather
|
|
29
|
-
than the JSON form it builds separately for the model.
|
|
30
|
-
|
|
31
|
-
**What this rules out:** widening the check to `'__credentialRequired' in
|
|
32
|
-
result` for convenience, or introducing any path where a credential request is
|
|
33
|
-
reconstructed from parsed JSON rather than passed by reference — either one
|
|
34
|
-
silently converts the gate into a formality. Note the inverse holds for the
|
|
35
|
-
`credentialFilteredChannel` suppression later in the same file: that one
|
|
36
|
-
deliberately matches the _string_ key, because it hides tool results from the
|
|
37
|
-
client and a broader match leaks less, not more.
|
package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: An agent requires a session only when auth is true, but always enforces scopes and permissions
|
|
4
|
-
description: Agents follow pikkuSessionlessFunc semantics so crons and queue workers can run them; scopes are an AND gate checked before any permission I/O
|
|
5
|
-
tags: agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# An agent requires a session only when auth is true, but always enforces scopes and permissions
|
|
9
|
-
|
|
10
|
-
`assertAgentAuthorized` in
|
|
11
|
-
`packages/core/src/wirings/agent/agent-prepare.ts` enforces, in order:
|
|
12
|
-
session presence (only when `CoreAgent.auth === true`), then `scopes`, then
|
|
13
|
-
`permissions`. The ordering mirrors the function runner — scopes AND together so
|
|
14
|
-
they can only narrow access, and a missing scope short-circuits before any
|
|
15
|
-
permission function does I/O. Declared `scopes` are narrowed to the generated
|
|
16
|
-
`ScopeId` union in a project's `#pikku/scopes`, so an undeclared scope is a
|
|
17
|
-
compile error.
|
|
18
|
-
|
|
19
|
-
`auth` defaults to `false` (i.e. `pikkuSessionlessFunc`, not `pikkuFunc`) because
|
|
20
|
-
an agent is normally reached from a function that already enforced its own auth,
|
|
21
|
-
and is also run from genuinely sessionless contexts such as crons and queue
|
|
22
|
-
workers. Requiring a session by default would reject those without adding a real
|
|
23
|
-
gate. Global permissions are evaluated here too rather than assumed to have
|
|
24
|
-
already run, because an agent is reachable from entry points that never pass
|
|
25
|
-
through the function runner; re-evaluating an AND gate of side-effect-free
|
|
26
|
-
predicates is idempotent.
|
|
27
|
-
|
|
28
|
-
**What this rules out:** making `auth: true` the default; checking permissions
|
|
29
|
-
before scopes; skipping globals on the assumption a caller already ran them; and
|
|
30
|
-
moving the gate into the individual run/stream/resume entry points, where a new
|
|
31
|
-
entry point would silently miss it.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: An agent ownership failure never echoes the resource it refused
|
|
4
|
-
description: assertResourceOwner throws a bare ForbiddenError so the error cannot be used as an existence oracle, at the cost of thinner debugging output
|
|
5
|
-
tags: agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# An agent ownership failure never echoes the resource it refused
|
|
9
|
-
|
|
10
|
-
`assertResourceOwner` in
|
|
11
|
-
`packages/core/src/wirings/agent/agent-prepare.ts` compares a stored
|
|
12
|
-
thread/run `resourceId` against the caller's composed owner key and throws
|
|
13
|
-
`ForbiddenError('Not authorized to access this thread' | '… run')` on a
|
|
14
|
-
mismatch. The message deliberately carries no id.
|
|
15
|
-
|
|
16
|
-
Including the id would turn the endpoint into an existence oracle: a caller
|
|
17
|
-
enumerating thread ids could tell "exists but is not yours" apart from "does not
|
|
18
|
-
exist", which leaks the shape of other tenants' data even though no content is
|
|
19
|
-
returned.
|
|
20
|
-
|
|
21
|
-
**What this rules out:** improving the error message by interpolating the
|
|
22
|
-
`threadId`, `runId`, or owner key into it, and distinguishing not-found from
|
|
23
|
-
not-authorized on the read paths.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Resuming a suspended agent run re-runs the agent's authorization gate
|
|
4
|
-
description: Ownership of the run is not enough — a grant revoked while the run was suspended must block the approval
|
|
5
|
-
tags: agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Resuming a suspended agent run re-runs the agent's authorization gate
|
|
9
|
-
|
|
10
|
-
Both `resumeAgent` (`agent-stream.ts`) and `resumeAgentSync`
|
|
11
|
-
(`agent-runner.ts`) call `assertAgentAuthorized` after asserting run
|
|
12
|
-
ownership and before touching `agentRunState.resolveApproval`.
|
|
13
|
-
|
|
14
|
-
Ownership proves the run belongs to the caller, not that the caller may still
|
|
15
|
-
act on it: a suspension can outlive the permission that created it, and the whole
|
|
16
|
-
point of an approval gate is that the person approving is authorized at the
|
|
17
|
-
moment of approval. Resolving an approval is a persisted side effect, so the
|
|
18
|
-
gate must run before it, not after.
|
|
19
|
-
|
|
20
|
-
**What this rules out:** treating the ownership assertion as the complete
|
|
21
|
-
authorization check on the resume paths, and moving `assertAgentAuthorized`
|
|
22
|
-
below `resolveApproval` for convenience.
|