@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
package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A channel lifecycle acts as the session the socket upgrade established
|
|
4
|
-
description: onConnect and onDisconnect run with the userSession captured during the socket upgrade, both in the wire they receive and as the session service passed to runPikkuFunc
|
|
5
|
-
tags: core, channel, sessions, lifecycle
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A channel lifecycle acts as the session the socket upgrade established
|
|
9
|
-
|
|
10
|
-
`runChannelLifecycleWithMiddleware` in `packages/core/src/wirings/channel/channel-common.ts` takes an optional `userSession`. The comment says it is established while the socket upgrades, so `onConnect` can tell who connected (`channel-common.ts:43-47`). The same function also serves `connect` and `disconnect` (`channel-common.ts:38`).
|
|
11
|
-
|
|
12
|
-
The wire for the lifecycle is built from that session when one exists (`channel-common.ts:78`). The lifecycle function then runs through `runPikkuFunc` with `sessionService: userSession` (`channel-common.ts:84-93`). So the lifecycle reads and writes the same session the upgrade produced, for both connect and disconnect.
|
|
13
|
-
|
|
14
|
-
The related decision that records when the user id is stored is [a channel's user id is persisted only after onConnect middleware has run](../internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md).
|
|
15
|
-
|
|
16
|
-
**What this rules out:** running a channel's disconnect handler as a different identity than the one that connected the socket, and building the lifecycle wire without the upgrade session when one was established.
|
package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A channel requires a session unless it says auth: false
|
|
4
|
-
description: The channel-level requirement is auth !== false, and a message handler's own auth, when it is set, decides for that message in either direction
|
|
5
|
-
tags: core, channel, auth
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A channel requires a session unless it says auth: false
|
|
9
|
-
|
|
10
|
-
Both channel runners compute the channel-level requirement as
|
|
11
|
-
`channelConfig.auth !== false`: `packages/core/src/wirings/channel/channel-runner.ts:142`
|
|
12
|
-
and `packages/core/src/wirings/channel/channel-handler.ts:75`. An absent `auth`
|
|
13
|
-
therefore requires a session. `channel.types.ts:67-76` documents the same rule and
|
|
14
|
-
says why: a proxy in front of a channel needs to tell public from private.
|
|
15
|
-
|
|
16
|
-
Per message, `validateAuth` (`channel-handler.ts:49-65`) uses the channel's
|
|
17
|
-
`requiresSession` when the handler is a bare function or has no `auth` of its own
|
|
18
|
-
(`:50-58`). When the handler object sets `auth`, that value wins (`:58-60`). The
|
|
19
|
-
check then fails only when `auth` is true and there is no session (`:62-64`).
|
|
20
|
-
|
|
21
|
-
So a message handler's `auth: false` loosens a channel that requires a session for
|
|
22
|
-
that message, and `auth: true` tightens a public channel for that message. A
|
|
23
|
-
rejected message gets the reply described in the question
|
|
24
|
-
`unauthorized-channel-replies-escape-the-declared-out-type.md`.
|
|
25
|
-
|
|
26
|
-
**What this rules out:** treating a channel with no `auth` flag as public.
|
package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A credential's read path follows its declared type, never a missing value
|
|
4
|
-
description: The credential wire service reads a wire credential only from the user's store and a singleton only from the deployment, so an absent user value never falls back to the deployment's token
|
|
5
|
-
tags: core, credentials, wire, singleton
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A credential's read path follows its declared type, never a missing value
|
|
9
|
-
|
|
10
|
-
`packages/core/src/services/credential-wire-service.ts` decides where each
|
|
11
|
-
credential is read from. The doc comment says the choice is "decided by what the
|
|
12
|
-
credential IS — its declared type, as the wiring may have overridden it — and
|
|
13
|
-
never by whether a per-user lookup came back empty", because an absence-driven
|
|
14
|
-
fallback "would let a user who has not connected read the deployment's own token"
|
|
15
|
-
(`credential-wire-service.ts:6-10`).
|
|
16
|
-
|
|
17
|
-
The resolution type is `{ mode: 'wire' } | { mode: 'singleton' }`
|
|
18
|
-
(`credential-wire-service.ts:12`).
|
|
19
|
-
|
|
20
|
-
In `doLoad`, the user's store is read with `getAll(userId)`, and any name the
|
|
21
|
-
resolution marks `singleton` is skipped (`credential-wire-service.ts:103-104`).
|
|
22
|
-
The comment says this stops a user "in charge of a slot the deployment owns"
|
|
23
|
-
(`credential-wire-service.ts:116-121`).
|
|
24
|
-
|
|
25
|
-
`loadDeploymentCredentials` fetches only `singleton` names from the deployment
|
|
26
|
-
service (`credential-wire-service.ts:137-143`). A `wire` name is skipped there
|
|
27
|
-
(`credential-wire-service.ts:138`), and the comment says a wire credential "can
|
|
28
|
-
never pick up a platform value" (`credential-wire-service.ts:127-130`).
|
|
29
|
-
|
|
30
|
-
**What this rules out:** a `wire` credential falling back to the deployment's
|
|
31
|
-
value when the user has none, and a user's stored value being imported under a
|
|
32
|
-
name the deployment declared as `singleton`.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A credential's wire or singleton type is a literal the inspector checks at declaration
|
|
4
|
-
description: defineCredential is a no-op read by AST, so its type must be a literal 'wire' or 'singleton' and the inspector refuses any other value
|
|
5
|
-
tags: core, credentials, inspector, declaration
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A credential's wire or singleton type is a literal the inspector checks at declaration
|
|
9
|
-
|
|
10
|
-
`defineCredential` in `packages/core/src/wirings/credential/define-credential.ts` is a
|
|
11
|
-
no-op. Its doc comment says the CLI reads the call by AST, so "the declaration must
|
|
12
|
-
be a top-level literal" (`define-credential.ts:4-5`). `type: 'wire'` is per-user and
|
|
13
|
-
`type: 'singleton'` is platform-wide (`define-credential.ts:6`).
|
|
14
|
-
|
|
15
|
-
The inspector finds the call by its identifier (`packages/inspector/src/add/add-credential.ts:27`)
|
|
16
|
-
and requires a `type` property. Anything other than `'singleton'` or `'wire'` is a
|
|
17
|
-
critical error: "missing or has invalid 'type' property. Must be 'singleton' or
|
|
18
|
-
'wire'" (`add-credential.ts:64-68`).
|
|
19
|
-
|
|
20
|
-
The read path that follows from that type is in
|
|
21
|
-
[a credential's read path follows its declared type, never a missing value](a-credential-read-path-follows-its-declared-type-not-absence.md).
|
|
22
|
-
This note covers the declaration only: the type is decided where the credential is
|
|
23
|
-
declared, and the inspector rejects a declaration whose type is missing or not one of
|
|
24
|
-
the two literals.
|
|
25
|
-
|
|
26
|
-
**What this rules out:** computing a credential's type from a variable or at runtime,
|
|
27
|
-
and accepting a declaration whose type is missing or spelled differently.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A dropped audit write is always logged
|
|
4
|
-
description: The no-op audit service falls back to the singleton logger when the wire carries none, so an unconfigured audit call is never silent
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A dropped audit write is always logged
|
|
9
|
-
|
|
10
|
-
The no-op `AuditService` in `packages/core/src/services/audit-service.ts` is what
|
|
11
|
-
a function gets when it calls `audit.write()` without `audit: true` set on it.
|
|
12
|
-
Its `write` discards the event — but before it does, it warns once, and it looks
|
|
13
|
-
for a logger in two places: the wire's own, then the singleton passed to the
|
|
14
|
-
constructor.
|
|
15
|
-
|
|
16
|
-
The fallback is the point. `wire.logger` is an optional hook for a host that
|
|
17
|
-
wants invocation-scoped logging — core never sets it, so on every path core
|
|
18
|
-
itself drives, the singleton is the only source there is. With only
|
|
19
|
-
`this.wire.logger` the warning would be dropped every time.
|
|
20
|
-
An audit call that silently does nothing is the worst available outcome: the
|
|
21
|
-
function believes it is producing an audit trail, the trail does not exist, and
|
|
22
|
-
nothing anywhere says so. The warning names the function and the fix, and fires
|
|
23
|
-
once per instance so it cannot flood a hot path.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** narrowing the logger lookup to a single source,
|
|
26
|
-
downgrading the warning to `debug`, or removing it as noise from a service whose
|
|
27
|
-
whole job is to do nothing. If this class stops warning, an unconfigured audit
|
|
28
|
-
call becomes undetectable.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A first-party tracking cookie is written only after its purposes are consented
|
|
4
|
-
description: mintCookie writes a new cookie only when every purpose it requires is true in the consent record, and writes nothing on a wire with no HTTP response
|
|
5
|
-
tags: core, analytics, consent, cookies
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A first-party tracking cookie is written only after its purposes are consented
|
|
9
|
-
|
|
10
|
-
`packages/core/src/analytics/mint-cookie.ts` creates a first-party cookie when
|
|
11
|
-
none exists. The doc comment says writing the cookie "IS the act consent governs",
|
|
12
|
-
so a minter that runs before the banner is answered has already done what the
|
|
13
|
-
send gate was meant to prevent (`mint-cookie.ts:11-15`).
|
|
14
|
-
|
|
15
|
-
The consent check is `permitted`. It returns true when no purposes are required,
|
|
16
|
-
and otherwise requires each purpose to be exactly `true` in the consent record
|
|
17
|
-
(`mint-cookie.ts:29-35`). A purpose missing from the record counts as refused.
|
|
18
|
-
`mintCookie` runs that check after it has found no existing cookie and no cached
|
|
19
|
-
value (`mint-cookie.ts:72`).
|
|
20
|
-
|
|
21
|
-
An existing cookie is returned before the consent check (`mint-cookie.ts:63-64`).
|
|
22
|
-
Reading a cookie the visitor already holds is therefore not gated by consent. The
|
|
23
|
-
`overwrite` option is the only way to replace it (`mint-cookie.ts:19-26`).
|
|
24
|
-
|
|
25
|
-
A wire with no HTTP response returns `undefined` and writes nothing
|
|
26
|
-
(`mint-cookie.ts:70-71`), as the doc comment says for cron tasks and queue workers
|
|
27
|
-
(`mint-cookie.ts:50-53`).
|
|
28
|
-
|
|
29
|
-
The value is cached per wire, so a second call in one request returns the same
|
|
30
|
-
identity (`mint-cookie.ts:66-68`, `77`, and the comment at `mint-cookie.ts:46-48`).
|
|
31
|
-
|
|
32
|
-
**What this rules out:** writing a tracking cookie before its purposes are
|
|
33
|
-
consented, and minting an identity on a non-HTTP wire.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A function never receives the secret service
|
|
4
|
-
description: Every function-, permission- and auth-facing services type is bounded by SecretlessServices, so reaching for `secrets` in a function body is a type error rather than a lint
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A function never receives the secret service
|
|
9
|
-
|
|
10
|
-
`SecretlessServices<Services>` is `Omit<Services, 'secrets'>`
|
|
11
|
-
(`packages/core/src/types/core.types.ts`), and
|
|
12
|
-
`CoreSecretlessSingletonServices` built from it is the constraint every
|
|
13
|
-
function-, permission- and auth-facing type is bounded by
|
|
14
|
-
(`packages/core/src/function/functions.types.ts`). Destructuring `secrets`
|
|
15
|
-
inside a `pikkuFunc` body does not lint — it does not compile.
|
|
16
|
-
|
|
17
|
-
The rule itself is older than the type: a function holding a `SecretService` can
|
|
18
|
-
read every secret in the vault, which makes its blast radius the whole vault
|
|
19
|
-
rather than the one credential it needs, and makes "which secrets does this
|
|
20
|
-
function depend on?" unanswerable. `[PKU950]` enforces the same confinement for
|
|
21
|
-
a `SecretService` reaching a function under an alias, because a rename does not
|
|
22
|
-
change what it is. Encoding it in the type is what makes the honest mistake
|
|
23
|
-
impossible rather than merely reported: secrets are resolved where things are
|
|
24
|
-
constructed — `pikkuServices`, `pikkuWireServices`, addon service factories,
|
|
25
|
-
middleware — and the function is handed the configured client.
|
|
26
|
-
|
|
27
|
-
The cost is that a function which needs to _ask about_ a secret rather than read
|
|
28
|
-
one — "is this key set?", for a readiness or provisioning check — cannot do it
|
|
29
|
-
directly either. It goes through a service that holds `secrets` and exposes only
|
|
30
|
-
that question, which is how `@pikku/addon-console` checks whether an installed
|
|
31
|
-
addon's declared secrets are present.
|
|
32
|
-
|
|
33
|
-
**What this rules out:** widening a function's services type back to
|
|
34
|
-
`CoreServices` for a function that "only needs one secret", and passing the
|
|
35
|
-
secret service through under another name — the type follows the shape and
|
|
36
|
-
`[PKU950]` follows the type. It also rules out treating the absence as an
|
|
37
|
-
oversight to be patched with a cast.
|
package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A graph run starts at an entry node the graph declared
|
|
4
|
-
description: startNode may only name a node in meta.entryNodeIds, and no generated route offers it, because otherwise a caller picks which half of the graph to skip
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A graph run starts at an entry node the graph declared
|
|
9
|
-
|
|
10
|
-
`runWorkflowGraph` in
|
|
11
|
-
`packages/core/src/wirings/workflow/graph/graph-runner.ts` takes an optional
|
|
12
|
-
`startNode`. It used to accept any node id the graph contained, validated only
|
|
13
|
-
by `validateGraphReferences` (does the node exist) and `areDependenciesSatisfied`
|
|
14
|
-
(does its input reference another node). A node whose input is a literal or comes
|
|
15
|
-
from the trigger passes both — including a node that is only ever reached after a
|
|
16
|
-
validation, payment or approval node. Choosing it as the start does not skip the
|
|
17
|
-
gate so much as never reach it.
|
|
18
|
-
|
|
19
|
-
`startNode` is now checked against `meta.entryNodeIds`, the set the graph itself
|
|
20
|
-
declared, and the generated `POST /workflow/:workflowName/graph/:nodeId` route
|
|
21
|
-
that offered it to HTTP callers is gone.
|
|
22
|
-
|
|
23
|
-
The parameter stays, because it has a real internal user: `PikkuTriggerService`
|
|
24
|
-
(`packages/core/src/wirings/trigger/pikku-trigger-service.ts`) passes a target's
|
|
25
|
-
`startNode` when a trigger fires. That caller names a node the graph declared, so
|
|
26
|
-
the restriction costs it nothing.
|
|
27
|
-
|
|
28
|
-
**What this rules out:** re-exposing entry-node choice on a generated route, and
|
|
29
|
-
"validating" a `startNode` by existence or by dependency satisfaction — neither
|
|
30
|
-
says the graph meant that node to be an entry point. It does not rule out a graph
|
|
31
|
-
declaring several entry nodes; that is exactly how a graph says which starts are
|
|
32
|
-
legitimate. If a graph needs a start that is not an entry node, the answer is to
|
|
33
|
-
declare it as one, not to widen the check.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A permission gets a wire it cannot reply on
|
|
4
|
-
description: The permission wire is typed with Out = never so a permission cannot send on the channel; that narrowing is not a subtype, so the call site asserts
|
|
5
|
-
tags: core, permissions
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A permission gets a wire it cannot reply on
|
|
9
|
-
|
|
10
|
-
`CorePikkuPermission` in `packages/core/src/function/functions.types.ts` types
|
|
11
|
-
its wire as `PikkuWire<In, never, false, any, PikkuRPC, never, never>`. The
|
|
12
|
-
second parameter is `Out`, and `never` there is deliberate: it makes
|
|
13
|
-
`wire.channel` a `PikkuChannel<unknown, never, …>`, whose `send` accepts
|
|
14
|
-
nothing. A permission is a gate — it answers `true` or `false` — and must not
|
|
15
|
-
be able to write a reply to the caller it is deciding about. A permission that
|
|
16
|
-
could `send` would be able to leak the very data the gate exists to withhold,
|
|
17
|
-
and it would do so before the function it guards has run.
|
|
18
|
-
|
|
19
|
-
`runPikkuFunc` holds an ordinary `PikkuWire`, whose default `Out` is `unknown`.
|
|
20
|
-
`unknown` is not assignable to `never`, and `send` is contravariant in its
|
|
21
|
-
argument, so the narrowing cannot be expressed as a subtype relation — the call
|
|
22
|
-
into `runPermissions` asserts to the exact permission-wire type rather than
|
|
23
|
-
relying on assignability.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** widening `Out` on the permission wire to `unknown` to
|
|
26
|
-
delete the assertion. That silently hands every permission function a working
|
|
27
|
-
`channel.send`. It equally rules out replacing the assertion with `as any`,
|
|
28
|
-
which erases the target type and hides the fact that a specific, intentional
|
|
29
|
-
narrowing is happening.
|
|
30
|
-
|
|
31
|
-
The same reasoning explains the `never` in the fifth and sixth positions
|
|
32
|
-
(`MCPTools`, `IsChannel`): a permission is not an MCP tool host and does not own
|
|
33
|
-
the channel lifecycle.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A public function says so with auth: false
|
|
4
|
-
description: An exposed sessionless function that writes auth: false is public on purpose and PKU574 stays quiet; one that leaves auth out still warns
|
|
5
|
-
tags: authorization, inspector, rpc
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A public function says so with auth: false
|
|
9
|
-
|
|
10
|
-
PKU574 warns about an exposed sessionless function with no gate. Some of those
|
|
11
|
-
are exactly what the author meant: a published programme, a price list, a health
|
|
12
|
-
check. Before this, the only way to quiet the warning on one was a gate that
|
|
13
|
-
gated nothing — an always-true permission, or `permissionsInBody: true`, which
|
|
14
|
-
claims a check the body does not make. Both put a false statement into meta to
|
|
15
|
-
silence a true one, and the alternative, living with the warning, teaches
|
|
16
|
-
everyone to stop reading it.
|
|
17
|
-
|
|
18
|
-
`auth: false` is already the field that says "no session required". Writing it
|
|
19
|
-
on a `pikkuSessionlessFunc` is redundant at runtime — sessionless already means
|
|
20
|
-
that — which is what makes it useful as a declaration: nobody writes it by
|
|
21
|
-
accident, so its presence is the author deciding the function is public. The
|
|
22
|
-
inspector now records `auth` as written (`true`, `false` or absent) instead of
|
|
23
|
-
folding `false` into absent, and the check treats `false` as a gate the author
|
|
24
|
-
declared, the same way it treats `permissionsInBody`.
|
|
25
|
-
|
|
26
|
-
The case the warning exists for is unchanged. A sessionless function that picked
|
|
27
|
-
up `expose: true` later, with nobody thinking about who may call it, has no
|
|
28
|
-
`auth` at all — and still warns.
|
|
29
|
-
|
|
30
|
-
**What this rules out:** a separate `public: true` flag, which would be a second
|
|
31
|
-
field meaning what `auth: false` already means; reading `readonly` or the
|
|
32
|
-
function's name as evidence it is safe to expose; and silencing PKU574 for every
|
|
33
|
-
sessionless function, which would drop the accidental-exposure case with the
|
|
34
|
-
intentional one.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A readonly session reaches only functions declared readonly
|
|
4
|
-
description: A session flagged readonly is refused by every function not declared readonly, checked straight after the session is required and before scopes
|
|
5
|
-
tags: core, auth, function-runner
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A readonly session reaches only functions declared readonly
|
|
9
|
-
|
|
10
|
-
`CoreUserSession.readonly` (`packages/core/src/types/core.types.ts`) restricts a
|
|
11
|
-
session to functions declared `readonly`. In `runPikkuFunc`
|
|
12
|
-
(`packages/core/src/function/function-runner.ts`) the check is
|
|
13
|
-
`if (session?.readonly && !funcMeta.readonly) throw new ReadonlySessionError()`.
|
|
14
|
-
It runs after the missing-session check and before scopes, permissions and input
|
|
15
|
-
validation, so a readonly session is refused before any work is done for a
|
|
16
|
-
mutating function. The unit test "should reject readonly sessions for
|
|
17
|
-
non-readonly functions" in `function-runner.test.ts` pins the behaviour.
|
|
18
|
-
|
|
19
|
-
Core never sets the flag. Whoever builds the session decides it, and core only
|
|
20
|
-
enforces it. Readonly is a property of the session, not of a scope, so a scope
|
|
21
|
-
grant cannot widen what a readonly session may reach.
|
|
22
|
-
|
|
23
|
-
**What this rules out:** expressing read-only access as a scope the session
|
|
24
|
-
happens to lack, and letting a readonly session call a mutating function on the
|
|
25
|
-
grounds that its scopes cover it.
|
package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scaffold flag says a surface exists, not who may call it
|
|
4
|
-
description: scaffold.<feature> is boolean | { path } — the auth field is gone, because the function runner already enforces each generated function's own auth, wiring, scopes and addon
|
|
5
|
-
tags: config, authorization, codegen, scaffold
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scaffold flag says a surface exists, not who may call it
|
|
9
|
-
|
|
10
|
-
`scaffold.<feature>` carried an `auth` field, defaulting closed — see
|
|
11
|
-
[[scaffold-features-are-authenticated-unless-opted-out]], which this supersedes.
|
|
12
|
-
The field is gone. `PikkuScaffoldFeature` is now `boolean | { path?: string }`:
|
|
13
|
-
whether the surface is generated, and where the file goes.
|
|
14
|
-
|
|
15
|
-
The field was a second gate in front of one that already runs. `resolveSession`
|
|
16
|
-
in `packages/core/src/function/function-runner.ts` (line 64) only loads a stored
|
|
17
|
-
session; it throws nothing. The refusal is in `executeFunction`: a `pikkuFunc`
|
|
18
|
-
with no session throws `MissingSessionError` (line 402, class at
|
|
19
|
-
`packages/core/src/errors/errors.ts:36`), unconditionally. A
|
|
20
|
-
`pikkuSessionlessFunc` throws the same error (line 392) only when its own
|
|
21
|
-
`auth: true` says so, when its wiring says so, or when `resolveAddonAuth` does. That is where authentication is decided, per function,
|
|
22
|
-
by whoever wrote it. Neither refusal is a `ForbiddenError`: both throw `MissingSessionError`
|
|
23
|
-
(`function-runner.ts:392`, `:402`; class at `packages/core/src/errors/errors.ts:36`). The split between
|
|
24
|
-
that error, `MissingScopeError` and `ForbiddenError` is recorded in
|
|
25
|
-
[a call without a session raises MissingSessionError](./a-call-without-a-session-raises-missing-session-not-forbidden.md). A config flag three directories away could only be coarser
|
|
26
|
-
than that, and being coarser was the whole problem the earlier decision was
|
|
27
|
-
trying to work around by defaulting it closed.
|
|
28
|
-
|
|
29
|
-
So the generated dispatchers — public RPC, public agent, workflow routes and the
|
|
30
|
-
events channel — emit a fixed `auth: false` on every function and wiring they
|
|
31
|
-
write. That is not the scaffold declaring the surface public. It is the
|
|
32
|
-
dispatcher declining to gate, because it does not know what it is forwarding to:
|
|
33
|
-
`rpcCaller` hands whatever name it was given to `rpc.exposed`, and the function
|
|
34
|
-
that resolves there is the one that answers for itself. Omitting the field would
|
|
35
|
-
not have been neutral — a wiring with no `auth` requires a session — so the
|
|
36
|
-
wrapper would reject the call before the gate that decides ever ran, which is a
|
|
37
|
-
harder gate than the config field it replaced, applied by the layer least
|
|
38
|
-
qualified to apply it.
|
|
39
|
-
|
|
40
|
-
The scoped admin surfaces do not emit it. `userAdmin` and `virtualUser` generate
|
|
41
|
-
`pikkuFunc` with `scopes: ['admin:users:...']` — session-required by
|
|
42
|
-
construction, and the function that decides rather than a wrapper in front of
|
|
43
|
-
one. `auth: false` there is refused by `runPikkuFunc` with a warning telling you
|
|
44
|
-
to use `pikkuSessionlessFunc` instead, and `auth: true` would only restate the
|
|
45
|
-
type.
|
|
46
|
-
|
|
47
|
-
`pikku enable <feature>` lost its `--noAuth` flag with the field it wrote.
|
|
48
|
-
|
|
49
|
-
**What this rules out:** reading a scaffold flag as an authorization decision;
|
|
50
|
-
gating a surface in the config instead of on the function that answers it; and
|
|
51
|
-
letting a generated dispatcher inherit the default `auth: true`, which reads as
|
|
52
|
-
"undecided" and behaves as "denied".
|
package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scheduled virtual-user run needs no admin at run time
|
|
4
|
-
description: An admin may start a virtual-user run, but the run itself never depends on an admin being signed in or on an admin's credential
|
|
5
|
-
tags: services, auth, workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scheduled virtual-user run needs no admin at run time
|
|
9
|
-
|
|
10
|
-
The people who set up virtual-user runs are not technical. A run must keep
|
|
11
|
-
working after they stop being around, and it must not depend on any admin being
|
|
12
|
-
signed in or on any admin's credential.
|
|
13
|
-
|
|
14
|
-
An admin clicking "run" or creating a schedule is the authorization step. Once
|
|
15
|
-
the schedule exists, the run is started by the app's own scheduler and performs
|
|
16
|
-
the test as a provisioned test account (see
|
|
17
|
-
[virtual-user-flagged users only](virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md)).
|
|
18
|
-
|
|
19
|
-
The run presents no credential at all. `executeVirtualUserRun`
|
|
20
|
-
(`packages/core/src/wirings/virtual-user/virtual-user-scaffold.ts`) builds its
|
|
21
|
-
virtual users with `signIn: inProcessSignIn(auth)`, which calls the app's
|
|
22
|
-
server-only sign-in endpoint through `auth.api`
|
|
23
|
-
(`packages/core/src/services/virtual-user-sign-in.ts`). The code asking is the
|
|
24
|
-
app, so there is no key for an admin to hold or refresh.
|
|
25
|
-
|
|
26
|
-
**What this rules out:** a run that borrows an admin's session or key, and a run
|
|
27
|
-
that depends on a person to refresh a credential.
|
package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scoped credential service is limited to the names its package declared
|
|
4
|
-
description: ScopedCredentialService refuses any credential name outside the package's declared set, filters getAll to that set, and refuses to enumerate users
|
|
5
|
-
tags: core, credentials, scoping
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scoped credential service is limited to the names its package declared
|
|
9
|
-
|
|
10
|
-
`packages/core/src/services/scoped-credential-service.ts` wraps a
|
|
11
|
-
`CredentialService` with the set of names a package declared. The doc comment
|
|
12
|
-
says it "cannot reach a credential it never declared, or enumerate the app's
|
|
13
|
-
users" (`scoped-credential-service.ts:6-9`).
|
|
14
|
-
|
|
15
|
-
- `get`, `set`, `delete`, `has` and `getUsersWithCredential` each call
|
|
16
|
-
`assertAllowed` and throw `Access denied to credential` for an undeclared name
|
|
17
|
-
(`scoped-credential-service.ts:16-20`, `23`, `28`, `33`, `38`, `54`).
|
|
18
|
-
- `getAll(userId)` returns only the declared names that the user holds
|
|
19
|
-
(`scoped-credential-service.ts:42-51`).
|
|
20
|
-
- `getAllUsers` always throws (`scoped-credential-service.ts:58-62`).
|
|
21
|
-
|
|
22
|
-
Writes are allowed for declared names (`scoped-credential-service.ts:27-30`), per
|
|
23
|
-
the doc comment at `scoped-credential-service.ts:6-8`.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** a package reading or writing another package's
|
|
26
|
-
credential, and a package listing every user of the app.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scoped secret view reads only its declared keys and never writes
|
|
4
|
-
description: ScopedSecretService checks every read against an allowed-key set and refuses all writes, unlike the credential service that stays writable
|
|
5
|
-
tags: core, secrets, scoping
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scoped secret view reads only its declared keys and never writes
|
|
9
|
-
|
|
10
|
-
`packages/core/src/services/scoped-secret-service.ts` wraps a `SecretService`
|
|
11
|
-
with a set of allowed keys (`scoped-secret-service.ts:4-8`).
|
|
12
|
-
|
|
13
|
-
Every read is checked first. `getSecret`, `hasSecret` and `getSecrets` each call
|
|
14
|
-
`assertAllowed`, which throws `Access denied to secret key` for any key outside
|
|
15
|
-
the set (`scoped-secret-service.ts:10-14`, `17`, `22`, `43`).
|
|
16
|
-
|
|
17
|
-
Every write is refused. `setSecret`, `setEncryptedSecret` and `deleteSecret`
|
|
18
|
-
throw unconditionally (`scoped-secret-service.ts:26-38`).
|
|
19
|
-
|
|
20
|
-
The credential counterpart is different. `scoped-credential-service.ts` says it
|
|
21
|
-
"stays writable — an addon refreshing its own OAuth token is the normal case"
|
|
22
|
-
(`scoped-credential-service.ts:6-8`).
|
|
23
|
-
|
|
24
|
-
**What this rules out:** an addon reading a secret it did not declare, and an
|
|
25
|
-
addon writing or deleting any secret through this view.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A secret may only be sent to the hosts its declaration names
|
|
4
|
-
description: assertSecretAllowedForHost refuses a host outside a secret's allowedHosts, and refuses any host at all for a secret with no allowedHosts when the project requires them
|
|
5
|
-
tags: core, secrets, egress
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A secret may only be sent to the hosts its declaration names
|
|
9
|
-
|
|
10
|
-
`packages/core/src/services/secret-host-binding.ts` holds the check
|
|
11
|
-
`assertSecretAllowedForHost`. It looks up the secret's definition by id and reads
|
|
12
|
-
its `allowedHosts` (`secret-host-binding.ts:36-39`).
|
|
13
|
-
|
|
14
|
-
- No `allowedHosts`, and `requireAllowedHosts` is set: throw
|
|
15
|
-
(`secret-host-binding.ts:41-44`).
|
|
16
|
-
- No `allowedHosts`, and the flag is not set: allowed (`secret-host-binding.ts:45`).
|
|
17
|
-
- `allowedHosts` present: the host must match at least one entry, or throw
|
|
18
|
-
(`secret-host-binding.ts:48-50`).
|
|
19
|
-
|
|
20
|
-
Matching (`secret-host-binding.ts:18-26`) is case-insensitive. An entry is either
|
|
21
|
-
an exact host or a single leading `*.` wildcard. The wildcard requires a
|
|
22
|
-
non-empty label before the dot (`secret-host-binding.ts:23`), so `*.example.com`
|
|
23
|
-
does not match `example.com` itself.
|
|
24
|
-
|
|
25
|
-
The error message tells the author to add the host to `allowedHosts` on the
|
|
26
|
-
`defineSecret` if the send is intended (`secret-host-binding.ts:11`).
|
|
27
|
-
|
|
28
|
-
**What this rules out:** sending a secret to a host its declaration does not
|
|
29
|
-
name, and a bare-domain match against a wildcard entry.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scenario step can name an identity no virtual user holds, through per-call headers
|
|
4
|
-
description: ScenarioInvokeOptions.headers lets a step send an impersonation or shim header on one call, and a virtual-user run never gets that option
|
|
5
|
-
tags: core, virtual-users, scenario
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scenario step can name an identity no virtual user holds, through per-call headers
|
|
9
|
-
|
|
10
|
-
`ScenarioInvokeOptions` in `packages/core/src/services/virtual-users-service.ts` says
|
|
11
|
-
its headers are how "a step expresses an identity no declared virtual user can — an
|
|
12
|
-
impersonation header, or one of the header-shim principals a credential scenario
|
|
13
|
-
invents." `HttpVirtualUser.invokeRaw` passes them to `postRpc`
|
|
14
|
-
(`packages/core/src/services/http-virtual-users.ts`), so they go out on that one call
|
|
15
|
-
alongside the virtual user's session.
|
|
16
|
-
|
|
17
|
-
The option belongs to the scenario author, who writes the steps and is trusted to
|
|
18
|
-
say which identity a check needs. A virtual-user run does not get it. Its target in
|
|
19
|
-
`packages/core/src/wirings/virtual-user/virtual-user-target.ts` calls
|
|
20
|
-
`virtualUser.invokeRaw(rpcName, args)` with no options, so an adversarial run cannot
|
|
21
|
-
add a header to reach an identity its virtual user does not hold.
|
|
22
|
-
|
|
23
|
-
**What this rules out:** giving a virtual-user run a per-call header, and removing the
|
|
24
|
-
option from scenario steps on the grounds that a declared virtual user should be the
|
|
25
|
-
only identity a step can use.
|
package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A step runs the function the workflow dispatched it with
|
|
4
|
-
description: StepState records the step's function name so the worker can reject a queue message naming a different one, because the step executes under the run owner's identity
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A step runs the function the workflow dispatched it with
|
|
9
|
-
|
|
10
|
-
`pikkuWorkflowStepWorker` (`workflow-queue-workers.ts`) takes `rpcName` straight
|
|
11
|
-
off the queue message and hands it to `executeWorkflowStep`. That call runs as
|
|
12
|
-
the run's owner — `invokeStepRpc` copies `run.wire.pikkuUserId` onto the wire —
|
|
13
|
-
and `rpcWithWire` does not apply the `expose` gate that the public `/rpc` route
|
|
14
|
-
applies. So the message decided both _what_ ran and _as whom_.
|
|
15
|
-
|
|
16
|
-
The claim in `executeWorkflowStepInner` read the step's status and nothing else;
|
|
17
|
-
there was no stored function name to compare against. `StepState` now carries
|
|
18
|
-
`rpcName`, written by `insertStepState` (which already received it) and returned
|
|
19
|
-
by every backend, and the claim rejects a message naming anything else with
|
|
20
|
-
`WorkflowStepFunctionMismatchError` — before any status is mutated, so a forged
|
|
21
|
-
message leaves the run untouched. The graph path takes the same value from
|
|
22
|
-
`nodes[nodeId].rpcName` rather than from the message.
|
|
23
|
-
|
|
24
|
-
`rpcName: undefined` means a store that never recorded one and cannot be
|
|
25
|
-
compared; `null` is a step with no function of its own. Only a recorded value is
|
|
26
|
-
checked.
|
|
27
|
-
|
|
28
|
-
**Reachability, stated plainly:** the step-worker queue is not reachable from the
|
|
29
|
-
public `/rpc/:rpcName` route — the worker is registered without `expose`. The
|
|
30
|
-
exposure this closes is write access to the queue backend, and any in-process
|
|
31
|
-
caller reaching `executeWorkflowStep` directly.
|
|
32
|
-
|
|
33
|
-
**What this rules out:** trusting a queue payload to name the function it
|
|
34
|
-
executes, here or in any future worker, and dropping `rpcName` from `StepState`
|
|
35
|
-
as redundant with the step data — the comparison is the only thing standing
|
|
36
|
-
between queue-write access and running any registered function as the run's
|
|
37
|
-
owner.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Stopping an agent run by its id skips the ownership check; interruptAgent is the checked path
|
|
4
|
-
description: signalRunInterrupt is exported and performs no authorisation, while interruptAgent asserts the run's resource owner before it signals
|
|
5
|
-
tags: core, agent, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Stopping an agent run by its id skips the ownership check; interruptAgent is the checked path
|
|
9
|
-
|
|
10
|
-
`signalRunInterrupt` in `packages/core/src/wirings/agent/agent-interrupt.ts:227-236`
|
|
11
|
-
looks up the run and aborts it, with no check on who is asking. Its doc comment at
|
|
12
|
-
`:215-220` says so directly: anyone holding a `runId` can stop the run, and callers
|
|
13
|
-
should use `interruptAgent` unless the run's ownership is already established.
|
|
14
|
-
|
|
15
|
-
It is exported from the agent entry point (`packages/core/src/wirings/agent/index.ts:33`).
|
|
16
|
-
|
|
17
|
-
`interruptAgent` in `packages/core/src/wirings/agent/agent-stream.ts:1061-1086`
|
|
18
|
-
loads the run (`:1070`), asserts the resource owner with `assertResourceOwner`
|
|
19
|
-
(`:1074-1082`), and only then calls `signalRunInterrupt` (`:1084`). The RPC wrapper
|
|
20
|
-
calls `interruptAgent` (`packages/core/src/wirings/agent/agent-rpc.ts:98`).
|
|
21
|
-
|
|
22
|
-
**What this rules out:** exposing `signalRunInterrupt` to a caller who has not
|
|
23
|
-
resolved the run's owner, and reaching a run through its id alone on a request
|
|
24
|
-
path.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A vault secret redacts when serialized and throws when coerced to a string
|
|
4
|
-
description: SecretValue serializes to a redacted marker so logs stay honest without crashing, but string coercion throws, and reveal() is the only way to read the value
|
|
5
|
-
tags: core, secrets, classification
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A vault secret redacts when serialized and throws when coerced to a string
|
|
9
|
-
|
|
10
|
-
`packages/core/src/classification/secret-value.ts` wraps a vault value in
|
|
11
|
-
`SecretValue`. The raw value sits in a private field (`secret-value.ts:37`) and
|
|
12
|
-
is returned only by `reveal()` (`secret-value.ts:43-45`).
|
|
13
|
-
|
|
14
|
-
Two paths out of the wrapper behave differently on purpose:
|
|
15
|
-
|
|
16
|
-
- Structured serialization is redacted. `toJSON` and the Node inspect hook both
|
|
17
|
-
return `REDACTED`, which is `[secret]` (`secret-value.ts:5`, `47-53`). The doc
|
|
18
|
-
comment says an audit or log write "must stay honest about the field without
|
|
19
|
-
crashing the request" (`secret-value.ts:29-30`).
|
|
20
|
-
- String coercion throws. `toString` and `Symbol.toPrimitive` both throw
|
|
21
|
-
`SecretCoercionError` (`secret-value.ts:55-61`). The comment says "a template
|
|
22
|
-
literal or concatenation is always a leak" (`secret-value.ts:31`).
|
|
23
|
-
|
|
24
|
-
The `Safe<T>` type (`secret-value.ts:91-106`) rejects a `SecretValue` anywhere
|
|
25
|
-
in a type, for sinks typed `any`, `unknown` or a free generic.
|
|
26
|
-
|
|
27
|
-
**What this rules out:** reading a secret without calling `reveal()`, putting a
|
|
28
|
-
secret into a template literal or string concatenation, and a logger that
|
|
29
|
-
crashes on a secret field instead of redacting it.
|