@pikku/core 0.12.143 → 0.12.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/analytics.d.ts +14 -0
- package/dist/analytics/analytics.js +14 -0
- package/dist/analytics/analytics.types.d.ts +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +1 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +1 -0
- package/dist/analytics/mint-cookie.d.ts +1 -0
- package/dist/{wirings/channel/channel-middleware-runner.d.ts → channel-middleware-runner.d.ts} +17 -3
- package/dist/{wirings/channel/channel-middleware-runner.js → channel-middleware-runner.js} +24 -8
- package/dist/classification/data-classification.d.ts +13 -0
- package/dist/classification/secret-value.d.ts +7 -0
- package/dist/classification/secret-value.js +7 -0
- package/dist/crypto-utils.d.ts +93 -0
- package/dist/crypto-utils.js +92 -0
- package/dist/dev/hot-reload.d.ts +16 -0
- package/dist/dev/hot-reload.js +16 -1
- package/dist/dev/module-runner.js +7 -3
- package/dist/dev/reload-meta.js +1 -1
- package/dist/errors/error-handler.d.ts +9 -0
- package/dist/errors/error-handler.js +8 -0
- package/dist/errors/errors.d.ts +219 -0
- package/dist/errors/errors.js +227 -0
- package/dist/errors/serialized-error.d.ts +4 -0
- package/dist/function/abort-scope.d.ts +5 -0
- package/dist/function/function-meta.types.d.ts +20 -0
- package/dist/function/function-runner.d.ts +41 -0
- package/dist/function/function-runner.js +57 -11
- package/dist/function/functions.types.d.ts +59 -0
- package/dist/function/functions.types.js +23 -0
- package/dist/function/list.types.d.ts +4 -0
- package/dist/lifecycle.d.ts +12 -1
- package/dist/lifecycle.js +12 -1
- package/dist/middleware/addon-scope-cap.d.ts +4 -0
- package/dist/middleware/addon-scope-cap.js +7 -3
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.js +5 -13
- package/dist/middleware/auth-cookie.js +3 -3
- package/dist/middleware/middleware-factories.d.ts +17 -0
- package/dist/middleware/middleware-factories.js +17 -0
- package/dist/middleware/middleware.types.d.ts +23 -0
- package/dist/middleware/remote-auth.d.ts +15 -0
- package/dist/middleware/remote-auth.js +18 -3
- package/dist/middleware/remote-jobs-secret.js +2 -10
- package/dist/middleware-runner.d.ts +7 -0
- package/dist/middleware-runner.js +23 -7
- package/dist/permissions.d.ts +13 -0
- package/dist/permissions.js +13 -0
- package/dist/pikku-state.d.ts +49 -0
- package/dist/pikku-state.js +49 -0
- package/dist/remote.js +20 -5
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +36 -0
- package/dist/services/agent-run-state-service.d.ts +8 -0
- package/dist/services/agent-runner-service.d.ts +24 -0
- package/dist/services/agent-storage-service.d.ts +8 -0
- package/dist/services/ai-embedding-service.d.ts +4 -0
- package/dist/services/audit-service.d.ts +48 -0
- package/dist/services/audit-service.js +22 -0
- package/dist/services/content-service.d.ts +34 -0
- package/dist/services/credential-wire-service.d.ts +9 -0
- package/dist/services/credential-wire-service.js +9 -0
- package/dist/services/deployment-service.d.ts +14 -0
- package/dist/services/email-service.d.ts +20 -0
- package/dist/services/email-template.d.ts +24 -0
- package/dist/services/email-template.js +12 -0
- package/dist/services/file-scenario-run-store.d.ts +5 -0
- package/dist/services/file-scenario-run-store.js +4 -0
- package/dist/services/gateway-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.js +5 -0
- package/dist/services/in-memory-lease-service.d.ts +5 -0
- package/dist/services/in-memory-lease-service.js +5 -0
- package/dist/services/in-memory-session-store.d.ts +4 -0
- package/dist/services/in-memory-session-store.js +4 -0
- package/dist/services/incoming-webhook-queue.d.ts +2 -0
- package/dist/services/incoming-webhook-queue.js +2 -0
- package/dist/services/incoming-webhook-service.d.ts +9 -1
- package/dist/services/incoming-webhook-service.js +1 -1
- package/dist/services/index.d.ts +1 -5
- package/dist/services/index.js +1 -5
- package/dist/services/jwt-service.d.ts +8 -0
- package/dist/services/lease-service.d.ts +5 -0
- package/dist/services/lease-service.js +1 -0
- package/dist/services/local-content-request-handler.d.ts +20 -0
- package/dist/services/local-content-request-handler.js +11 -0
- package/dist/services/local-content.d.ts +45 -0
- package/dist/services/local-content.js +35 -0
- package/dist/services/local-credential-service.d.ts +5 -0
- package/dist/services/local-credential-service.js +5 -0
- package/dist/services/local-email-service.d.ts +7 -0
- package/dist/services/local-email-service.js +7 -0
- package/dist/services/local-secrets.d.ts +8 -0
- package/dist/services/local-secrets.js +8 -0
- package/dist/services/local-variables.d.ts +6 -0
- package/dist/services/local-variables.js +6 -0
- package/dist/services/logger.d.ts +4 -0
- package/dist/services/logger.js +4 -0
- package/dist/services/meta-service.d.ts +38 -0
- package/dist/services/meta-service.js +6 -0
- package/dist/services/queue-webhook-service.d.ts +19 -0
- package/dist/services/queue-webhook-service.js +19 -0
- package/dist/services/remote-jobs.d.ts +8 -13
- package/dist/services/remote-jobs.js +3 -54
- package/dist/services/scenario-cookie-jar.d.ts +4 -0
- package/dist/services/scheduler-service.d.ts +13 -0
- package/dist/services/scheduler-service.js +8 -0
- package/dist/services/schema-service.d.ts +9 -0
- package/dist/services/scope-service.d.ts +10 -0
- package/dist/services/scoped-secret-service.d.ts +5 -0
- package/dist/services/scoped-secret-service.js +5 -0
- package/dist/services/secret-host-binding.d.ts +5 -0
- package/dist/services/secret-host-binding.js +5 -0
- package/dist/services/secret-service.d.ts +19 -1
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +6 -0
- package/dist/services/session-store.d.ts +5 -0
- package/dist/services/stub-tracker.d.ts +1 -0
- package/dist/services/temporary-file-service.d.ts +9 -0
- package/dist/services/temporary-file-service.js +9 -0
- package/dist/services/trigger-service.d.ts +4 -0
- package/dist/services/trigger-source-store.d.ts +13 -0
- package/dist/services/trigger-source-store.js +7 -0
- package/dist/services/typed-credential-service.d.ts +6 -0
- package/dist/services/typed-credential-service.js +5 -0
- package/dist/services/typed-secret-service.d.ts +12 -0
- package/dist/services/typed-secret-service.js +11 -0
- package/dist/services/typed-variables-service.d.ts +1 -0
- package/dist/services/user-session-service.d.ts +31 -1
- package/dist/services/user-session-service.js +29 -3
- package/dist/services/v8-coverage-service.d.ts +27 -0
- package/dist/services/v8-coverage-service.js +5 -0
- package/dist/services/variables-service.d.ts +8 -0
- package/dist/services/virtual-user-sign-in.d.ts +1 -0
- package/dist/services/virtual-user-statement.d.ts +8 -0
- package/dist/services/virtual-user-statement.js +4 -0
- package/dist/services/webhook-service.d.ts +25 -0
- package/dist/services/webhook-service.js +15 -0
- package/dist/services/workflow-service.d.ts +6 -0
- package/dist/test-utils.js +1 -1
- package/dist/testing/service-tests.d.ts +4 -0
- package/dist/time-utils.d.ts +15 -0
- package/dist/time-utils.js +14 -0
- package/dist/types/core.types.d.ts +80 -0
- package/dist/types/state.types.d.ts +4 -0
- package/dist/utils/hmac.d.ts +3 -0
- package/dist/utils/safe-fetch.d.ts +14 -0
- package/dist/utils/safe-fetch.js +13 -0
- package/dist/utils/stable-stringify.d.ts +11 -0
- package/dist/utils/stable-stringify.js +33 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +22 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +7 -0
- package/dist/wirings/addon/define-screens.d.ts +2 -0
- package/dist/wirings/addon/remote-addon-auth.d.ts +9 -0
- package/dist/wirings/addon/remote-addon-auth.js +5 -0
- package/dist/wirings/addon/wire-addon.d.ts +4 -0
- package/dist/wirings/addon/wire-remote-addon.d.ts +1 -0
- package/dist/wirings/agent/agent-agui.d.ts +14 -5
- package/dist/wirings/agent/agent-agui.js +17 -6
- package/dist/wirings/agent/agent-helpers.d.ts +61 -1
- package/dist/wirings/agent/agent-helpers.js +62 -2
- package/dist/wirings/agent/agent-interrupt.d.ts +5 -0
- package/dist/wirings/agent/agent-output.d.ts +20 -0
- package/dist/wirings/agent/agent-output.js +69 -0
- package/dist/wirings/agent/agent-prepare.d.ts +41 -0
- package/dist/wirings/agent/agent-prepare.js +38 -2
- package/dist/wirings/agent/agent-registry.d.ts +8 -0
- package/dist/wirings/agent/agent-registry.js +10 -4
- package/dist/wirings/agent/agent-runner.d.ts +33 -0
- package/dist/wirings/agent/agent-runner.js +40 -7
- package/dist/wirings/agent/agent-stream.d.ts +30 -0
- package/dist/wirings/agent/agent-stream.js +33 -11
- package/dist/wirings/agent/agent.types.d.ts +43 -0
- package/dist/wirings/agent/voice-input.d.ts +12 -0
- package/dist/wirings/agent/voice-input.js +12 -0
- package/dist/wirings/agent/voice-output.d.ts +14 -0
- package/dist/wirings/agent/voice-output.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.js +1 -2
- package/dist/wirings/agent-scorer/agent-scorer-registry.d.ts +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.d.ts +1 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.js +1 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +7 -0
- package/dist/wirings/channel/channel-common.js +1 -1
- package/dist/wirings/channel/channel-rpc.types.d.ts +5 -0
- package/dist/wirings/channel/channel-runner.d.ts +22 -0
- package/dist/wirings/channel/channel-runner.js +22 -0
- package/dist/wirings/channel/channel-store.d.ts +8 -0
- package/dist/wirings/channel/channel-store.js +7 -0
- package/dist/wirings/channel/channel.types.d.ts +18 -0
- package/dist/wirings/channel/define-channel-routes.d.ts +5 -0
- package/dist/wirings/channel/define-channel-routes.js +5 -0
- package/dist/wirings/channel/eventhub-service.d.ts +9 -0
- package/dist/wirings/channel/eventhub-store.d.ts +1 -0
- package/dist/wirings/channel/eventhub-store.js +1 -0
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/index.js +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -0
- package/dist/wirings/channel/local/local-channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +13 -0
- package/dist/wirings/channel/local/local-channel-runner.js +13 -0
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +1 -0
- package/dist/wirings/channel/local/local-eventhub-service.js +1 -0
- package/dist/wirings/channel/log-channels.d.ts +1 -0
- package/dist/wirings/channel/log-channels.js +1 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +5 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +5 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +32 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +31 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +8 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +8 -0
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +43 -0
- package/dist/wirings/cli/cli-runner.js +43 -0
- package/dist/wirings/cli/cli.types.d.ts +4 -0
- package/dist/wirings/cli/command-parser.d.ts +13 -0
- package/dist/wirings/cli/command-parser.js +16 -0
- package/dist/wirings/credential/credential-overrides.d.ts +1 -0
- package/dist/wirings/credential/credential.types.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.js +7 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +1 -0
- package/dist/wirings/flag/flag.types.d.ts +3 -0
- package/dist/wirings/gateway/gateway-runner.d.ts +23 -0
- package/dist/wirings/gateway/gateway-runner.js +23 -0
- package/dist/wirings/gateway/gateway.types.d.ts +3 -0
- package/dist/wirings/gateway/local-gateway-service.d.ts +10 -0
- package/dist/{services → wirings/gateway}/local-gateway-service.js +6 -2
- package/dist/wirings/http/http-routes.d.ts +21 -0
- package/dist/wirings/http/http-routes.js +11 -0
- package/dist/wirings/http/http-runner.d.ts +71 -0
- package/dist/wirings/http/http-runner.js +73 -5
- package/dist/wirings/http/http.types.d.ts +27 -0
- package/dist/wirings/http/index.d.ts +1 -0
- package/dist/wirings/http/index.js +1 -0
- package/dist/wirings/http/log-http-routes.d.ts +1 -0
- package/dist/wirings/http/log-http-routes.js +1 -0
- package/dist/wirings/http/merge-request-data.d.ts +12 -0
- package/dist/wirings/http/merge-request-data.js +42 -0
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.js +3 -32
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +1 -0
- package/dist/wirings/http/routers/http-router.d.ts +6 -0
- package/dist/wirings/http/routers/http-router.js +6 -0
- package/dist/wirings/http/web-request.d.ts +17 -0
- package/dist/wirings/http/web-request.js +17 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +7 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.js +7 -0
- package/dist/wirings/mcp/mcp-runner.d.ts +63 -0
- package/dist/wirings/mcp/mcp-runner.js +62 -0
- package/dist/wirings/mcp/mcp.types.d.ts +12 -0
- package/dist/wirings/node/node.types.d.ts +4 -0
- package/dist/wirings/oauth2/oauth2.types.d.ts +2 -0
- package/dist/{services → wirings/queue}/in-memory-queue-service.d.ts +9 -1
- package/dist/{services → wirings/queue}/in-memory-queue-service.js +9 -1
- package/dist/wirings/queue/index.d.ts +1 -0
- package/dist/wirings/queue/index.js +1 -0
- package/dist/wirings/queue/queue-identity.js +2 -14
- package/dist/wirings/queue/queue-runner.d.ts +37 -0
- package/dist/wirings/queue/queue-runner.js +37 -0
- package/dist/wirings/queue/queue.types.d.ts +35 -0
- package/dist/wirings/queue/register-queue-helper.d.ts +12 -0
- package/dist/wirings/queue/register-queue-helper.js +11 -0
- package/dist/wirings/queue/remote-queue-job.d.ts +11 -0
- package/dist/wirings/queue/remote-queue-job.js +41 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -0
- package/dist/wirings/role/role.types.d.ts +3 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +24 -0
- package/dist/wirings/rpc/rpc-runner.js +37 -2
- package/dist/wirings/rpc/rpc-types.d.ts +2 -0
- package/dist/wirings/scheduler/index.d.ts +1 -0
- package/dist/wirings/scheduler/index.js +1 -0
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -0
- package/dist/wirings/scheduler/log-schedulers.js +1 -0
- package/dist/wirings/scheduler/remote-scheduled-job.d.ts +11 -0
- package/dist/wirings/scheduler/remote-scheduled-job.js +20 -0
- package/dist/wirings/scheduler/scheduler-runner.d.ts +29 -0
- package/dist/wirings/scheduler/scheduler-runner.js +28 -0
- package/dist/wirings/scheduler/scheduler.types.d.ts +3 -0
- package/dist/wirings/scope/scope.types.d.ts +5 -0
- package/dist/wirings/secret/index.d.ts +2 -2
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +26 -1
- package/dist/wirings/secret/secret.types.js +1 -0
- package/dist/wirings/secret/validate-secret-definitions.d.ts +8 -0
- package/dist/wirings/secret/validate-secret-definitions.js +15 -0
- package/dist/wirings/trigger/in-memory-trigger-service.d.ts +11 -0
- package/dist/{services → wirings/trigger}/in-memory-trigger-service.js +10 -3
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +8 -3
- package/dist/wirings/trigger/pikku-trigger-service.js +14 -3
- package/dist/wirings/trigger/trigger-runner.d.ts +27 -2
- package/dist/wirings/trigger/trigger-runner.js +35 -2
- package/dist/wirings/trigger/trigger.types.d.ts +26 -4
- package/dist/wirings/trigger/webhook-source-runner.d.ts +24 -0
- package/dist/wirings/trigger/webhook-source-runner.js +19 -0
- package/dist/wirings/trigger/webhook-source.types.d.ts +12 -2
- package/dist/wirings/trigger/webhook-source.types.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +7 -0
- package/dist/wirings/variable/validate-variable-definitions.js +7 -0
- package/dist/wirings/variable/variable.types.d.ts +7 -0
- package/dist/wirings/virtual-user/conversation/conversation.types.d.ts +5 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +6 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.js +1 -1
- package/dist/{services → wirings/virtual-user}/http-virtual-users.d.ts +4 -3
- package/dist/{services → wirings/virtual-user}/http-virtual-users.js +6 -6
- package/dist/wirings/virtual-user/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.js +1 -1
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +2 -1
- package/dist/wirings/virtual-user/run-virtual-user.js +1 -14
- package/dist/wirings/virtual-user/virtual-user-declaration.types.d.ts +4 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +10 -1
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.js +1 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +1 -0
- package/dist/wirings/webhook/define-outgoing-webhook.d.ts +20 -0
- package/dist/wirings/webhook/define-outgoing-webhook.js +9 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +8 -4
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +7 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +7 -0
- package/dist/wirings/workflow/feature.d.ts +12 -0
- package/dist/wirings/workflow/feature.js +12 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +5 -0
- package/dist/wirings/workflow/graph/graph-node.js +5 -0
- package/dist/wirings/workflow/graph/template.d.ts +6 -0
- package/dist/wirings/workflow/graph/template.js +5 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +12 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +10 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +11 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +1 -0
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.d.ts +8 -3
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.js +9 -4
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +1 -1
- package/dist/wirings/workflow/pikku-scenario-service.js +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +1 -0
- package/dist/wirings/workflow/pikku-workflow-service.js +1 -0
- package/dist/wirings/workflow/run-timeline.d.ts +21 -0
- package/dist/wirings/workflow/run-timeline.js +15 -7
- package/dist/wirings/workflow/scenario-coverage.d.ts +1 -0
- package/dist/wirings/workflow/scenario-poll.d.ts +1 -0
- package/dist/wirings/workflow/scenario-prose.d.ts +6 -0
- package/dist/wirings/workflow/scenario-prose.js +6 -0
- package/dist/wirings/workflow/scenario-run.types.d.ts +3 -0
- package/dist/wirings/workflow/scenario-step.types.d.ts +1 -0
- package/dist/wirings/workflow/scenario-step.types.js +1 -0
- package/dist/wirings/workflow/scenario-surface.js +1 -13
- package/dist/wirings/workflow/scenario.types.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +6 -0
- package/dist/wirings/workflow/workflow-constants.d.ts +7 -1
- package/dist/wirings/workflow/workflow-constants.js +10 -1
- package/dist/wirings/workflow/workflow-errors.d.ts +13 -0
- package/dist/wirings/workflow/workflow-errors.js +13 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +4 -0
- package/dist/wirings/workflow/workflow-invocation-id.js +4 -0
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +3 -0
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +1 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +1 -0
- package/dist/wirings/workflow/workflow-status-stream.d.ts +1 -0
- package/dist/wirings/workflow/workflow-unwind-plan.js +2 -7
- package/dist/wirings/workflow/workflow.types.d.ts +40 -0
- package/package.json +26 -9
- package/CHANGELOG.md +0 -6978
- package/dist/services/in-memory-trigger-service.d.ts +0 -4
- package/dist/services/local-gateway-service.d.ts +0 -6
- package/dist/utils/hash.d.ts +0 -2
- package/dist/utils/hash.js +0 -23
- package/knowledge/decisions/index.md +0 -19
- package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +0 -29
- package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +0 -29
- package/knowledge/decisions/internals/a-held-run-is-woken-later-not-retried.md +0 -28
- package/knowledge/decisions/internals/a-latency-budget-is-asserted-by-its-cause.md +0 -32
- package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-agentrunstate-too.md +0 -22
- package/knowledge/decisions/internals/a-reset-suite-makes-the-dev-seed-the-fixture.md +0 -50
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +0 -20
- package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +0 -21
- package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +0 -22
- package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +0 -28
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +0 -49
- package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +0 -32
- package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +0 -66
- package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +0 -24
- package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +0 -21
- package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +0 -34
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +0 -65
- package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +0 -49
- package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +0 -45
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +0 -26
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +0 -32
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +0 -33
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +0 -28
- package/knowledge/decisions/internals/agent-agui-bridge-obeys-the-client-ordering-contract.md +0 -29
- package/knowledge/decisions/internals/agent-audio-chunks-carry-the-format-the-provider-returned.md +0 -20
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +0 -21
- package/knowledge/decisions/internals/agent-credential-suspensions-hide-the-tool-result.md +0 -26
- package/knowledge/decisions/internals/agent-delegate-and-supervise-hide-different-text.md +0 -26
- package/knowledge/decisions/internals/agent-llm-tool-arguments-have-nulls-stripped.md +0 -23
- package/knowledge/decisions/internals/agent-model-config-stays-a-single-resolution-seam.md +0 -25
- package/knowledge/decisions/internals/agent-onerror-hooks-cannot-change-the-failure.md +0 -22
- package/knowledge/decisions/internals/agent-runner-methods-must-keep-their-receiver.md +0 -22
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +0 -22
- package/knowledge/decisions/internals/agent-stream-persistence-is-best-effort.md +0 -27
- package/knowledge/decisions/internals/agent-sub-agents-inherit-the-parent-context-block.md +0 -26
- package/knowledge/decisions/internals/agent-tool-execute-failures-are-logged-unconditionally.md +0 -25
- package/knowledge/decisions/internals/agent-voice-input-transcribes-audio-parts-in-place.md +0 -22
- package/knowledge/decisions/internals/agent-working-memory-is-persisted-only-when-valid.md +0 -25
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +0 -39
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +0 -23
- package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +0 -27
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +0 -25
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +0 -22
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +0 -20
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +0 -22
- package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +0 -26
- package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +0 -66
- package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +0 -22
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +0 -30
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +0 -31
- package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +0 -33
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +0 -29
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +0 -28
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +0 -27
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +0 -28
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +0 -34
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +0 -29
- package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +0 -84
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +0 -41
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +0 -44
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +0 -39
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +0 -42
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +0 -39
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +0 -43
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +0 -38
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +0 -44
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +0 -27
- package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +0 -22
- package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +0 -28
- package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +0 -24
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +0 -32
- package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +0 -43
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +0 -28
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +0 -31
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +0 -26
- package/knowledge/decisions/internals/global-middleware-resolves-from-the-root-namespace-too.md +0 -32
- package/knowledge/decisions/internals/hot-reload-reads-the-changed-source-never-a-compiled-copy.md +0 -38
- package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +0 -26
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +0 -32
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +0 -28
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +0 -30
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +0 -26
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +0 -28
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +0 -32
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +0 -26
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +0 -25
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +0 -26
- package/knowledge/decisions/internals/index.md +0 -182
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +0 -25
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +0 -26
- package/knowledge/decisions/internals/mcp-wire-names-are-assigned-over-the-whole-registry.md +0 -39
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +0 -24
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +0 -53
- package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +0 -21
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +0 -28
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +0 -27
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +0 -31
- package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +0 -30
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +0 -32
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +0 -31
- package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +0 -24
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +0 -26
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +0 -27
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +0 -48
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +0 -30
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +0 -28
- package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +0 -34
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +0 -24
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +0 -26
- package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +0 -43
- package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +0 -22
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +0 -30
- package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +0 -83
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +0 -29
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +0 -27
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +0 -40
- package/knowledge/decisions/internals/the-mcp-handshake-is-challenged-only-when-every-target-is-gated.md +0 -29
- package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +0 -40
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +0 -40
- package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +0 -24
- package/knowledge/decisions/internals/the-runner-resolves-wire-services-itself.md +0 -31
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +0 -26
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +0 -25
- package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +0 -21
- package/knowledge/decisions/internals/the-virtual-user-prompt-says-json-because-of-json-object-mode.md +0 -22
- package/knowledge/decisions/internals/the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md +0 -28
- package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +0 -22
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +0 -25
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +0 -33
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +0 -26
- package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +0 -43
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +0 -115
- package/knowledge/decisions/internals/virtual-user-conversation-drives-the-target-through-a-transport-seam.md +0 -24
- package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +0 -25
- package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +0 -23
- package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +0 -21
- package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +0 -30
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +0 -24
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +0 -26
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +0 -25
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +0 -58
- package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +0 -35
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +0 -34
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +0 -42
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +0 -38
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +0 -29
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +0 -42
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +0 -25
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +0 -29
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +0 -43
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +0 -29
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +0 -42
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +0 -33
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +0 -32
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +0 -31
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +0 -39
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +0 -29
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +0 -33
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +0 -37
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +0 -54
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +0 -43
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +0 -32
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +0 -18
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +0 -34
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +0 -29
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +0 -33
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +0 -34
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +0 -34
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +0 -38
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +0 -30
- package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +0 -26
- package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +0 -20
- package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +0 -23
- package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +0 -16
- package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +0 -26
- package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +0 -32
- package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +0 -27
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +0 -28
- package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +0 -33
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +0 -37
- package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +0 -33
- package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +0 -33
- package/knowledge/decisions/security/a-public-function-says-so-with-auth-false.md +0 -34
- package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +0 -25
- package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +0 -52
- package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +0 -27
- package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +0 -26
- package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +0 -25
- package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +0 -29
- package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +0 -25
- package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +0 -37
- package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +0 -24
- package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +0 -29
- package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +0 -30
- package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +0 -38
- package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +0 -23
- package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +0 -41
- package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +0 -25
- package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +0 -32
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +0 -50
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +0 -43
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +0 -52
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +0 -46
- package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +0 -20
- package/knowledge/decisions/security/agent-approval-forwarding-requires-a-symbol-brand.md +0 -27
- package/knowledge/decisions/security/agent-credential-requests-are-symbol-branded.md +0 -37
- package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +0 -31
- package/knowledge/decisions/security/agent-ownership-failures-never-echo-the-resource.md +0 -23
- package/knowledge/decisions/security/agent-resume-re-runs-the-authorization-gate.md +0 -22
- package/knowledge/decisions/security/agent-sessionless-deployments-have-no-thread-ownership.md +0 -39
- package/knowledge/decisions/security/agent-thread-ownership-composes-the-session-principal.md +0 -30
- package/knowledge/decisions/security/agent-tool-filtering-reads-the-live-function-config.md +0 -24
- package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +0 -26
- package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +0 -33
- package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +0 -16
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +0 -33
- package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +0 -26
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +0 -59
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +0 -30
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +0 -52
- package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +0 -38
- package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +0 -31
- package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +0 -18
- package/knowledge/decisions/security/an-mcp-refusal-is-decided-before-dispatch.md +0 -48
- package/knowledge/decisions/security/an-oauth2-credential-is-read-by-its-account-row.md +0 -40
- package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +0 -32
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +0 -24
- package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +0 -24
- package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +0 -26
- package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +0 -27
- package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +0 -25
- package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +0 -18
- package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +0 -29
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +0 -84
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +0 -39
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +0 -37
- package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +0 -22
- package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +0 -29
- package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +0 -27
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +0 -41
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +0 -30
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +0 -40
- package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +0 -25
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +0 -33
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +0 -46
- package/knowledge/decisions/security/index.md +0 -135
- package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +0 -21
- package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +0 -38
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +0 -27
- package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +0 -18
- package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +0 -22
- package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +0 -26
- package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +0 -24
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +0 -40
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +0 -31
- package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +0 -35
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +0 -69
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +0 -39
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +0 -34
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +0 -55
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +0 -30
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +0 -28
- package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +0 -31
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +0 -34
- package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +0 -22
- package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +0 -34
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +0 -37
- package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +0 -26
- package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +0 -24
- package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +0 -16
- package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +0 -21
- package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +0 -24
- package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +0 -34
- package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +0 -16
- package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +0 -29
- package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +0 -23
- package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +0 -25
- package/knowledge/decisions/security/virtual-user-conversation-missing-approval-decisions-default-to-denied.md +0 -22
- package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +0 -18
- package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +0 -25
- package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +0 -42
- package/knowledge/decisions/security/virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +0 -29
- package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +0 -29
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +0 -25
- package/knowledge/decisions/security/wire-addon-expose-selects-the-rpc-surface.md +0 -51
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +0 -40
- package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +0 -18
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +0 -31
- package/knowledge/decisions/security/workflow-virtual-user-steps-always-use-the-real-transport.md +0 -34
- package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +0 -18
- package/knowledge/index.md +0 -24
- package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +0 -24
- package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +0 -35
- package/knowledge/questions/dev-quick-login-as-impersonation.md +0 -25
- package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +0 -26
- package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +0 -27
- package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +0 -26
- package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +0 -26
- package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +0 -34
- package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +0 -20
- package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +0 -24
- package/knowledge/questions/does-the-store-session-match-the-other-two.md +0 -19
- package/knowledge/questions/index.md +0 -41
- package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +0 -21
- package/knowledge/questions/live-scheduled-tests-may-write.md +0 -19
- package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +0 -23
- package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +0 -32
- package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +0 -25
- package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +0 -23
- package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +0 -35
- package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +0 -23
- package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +0 -27
- package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +0 -26
- package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +0 -20
- package/knowledge/questions/staging-impersonation-rules.md +0 -27
- package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +0 -44
- package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +0 -33
- package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +0 -20
- package/knowledge/questions/what-an-impersonated-session-carries.md +0 -22
- package/run-tests.sh +0 -68
- package/scripts/generate-api-report.d.mts +0 -1
- package/scripts/generate-api-report.mjs +0 -96
- package/scripts/generate-api-report.mts +0 -333
- package/src/public-surface.json +0 -637
- package/src/public-surface.json.README +0 -43
- /package/dist/{function/compensation-name.d.ts → compensation-name.d.ts} +0 -0
- /package/dist/{function/compensation-name.js → compensation-name.js} +0 -0
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Virtual user sign-in has one door, reached two ways
|
|
4
|
-
description: Only the app's virtual user sign-in handler creates a virtual user session; runs reach it in-process and everything else reaches it with a signed statement
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Virtual user sign-in has one door, reached two ways
|
|
9
|
-
|
|
10
|
-
The `signIn` closure in the Better Auth virtual user plugin
|
|
11
|
-
(`packages/services/better-auth/src/virtual-user-plugin.ts`) is the only thing that
|
|
12
|
-
creates a virtual user session. It refuses any user row not flagged `virtualUser`,
|
|
13
|
-
creates a row only under `pikku dev` (`mayProvision`), and sets the session cookie.
|
|
14
|
-
Every route below ends in it; nothing else mints a session for a virtual user.
|
|
15
|
-
|
|
16
|
-
**Runs go in-process.** A run — started by a person, or by the scheduled tick as
|
|
17
|
-
`pikku-platform` holding only `virtualUser:run` — already executes inside the app, so
|
|
18
|
-
it has nothing to prove to itself. It calls `auth.api.signInVirtualUserInternal`, an
|
|
19
|
-
endpoint marked `metadata: { SERVER_ONLY: true }`: better-call leaves it out of the
|
|
20
|
-
router, so `auth.handler` answers 404 for its path while `auth.api` can still call it.
|
|
21
|
-
The seam is `services.auth`, which core already types structurally, so core imports
|
|
22
|
-
nothing from Better Auth and a project without it gets an error that says so.
|
|
23
|
-
|
|
24
|
-
**Everything outside the app presents a signed statement** — see
|
|
25
|
-
[an external caller presents one signed statement](an-external-virtual-user-caller-presents-one-signed-statement.md).
|
|
26
|
-
That covers the dev switcher, `pikku scenario run`, `pikku virtual-user run` and
|
|
27
|
-
`rpc`, `pikku pages screenshot --as`, and the Playwright provider.
|
|
28
|
-
|
|
29
|
-
Two choices fall out of this and are deliberate:
|
|
30
|
-
|
|
31
|
-
- **Cookie, not bearer.** The run takes the `Set-Cookie` values from the in-process
|
|
32
|
-
call into the cookie jar core already has, then drives the app over HTTP with it.
|
|
33
|
-
Apps do not register Better Auth's bearer plugin and this does not make them.
|
|
34
|
-
- **A public URL, not a service binding.** The run is a queue worker unit and the
|
|
35
|
-
existing bindings carry RPC, not HTTP. It reads `VIRTUAL_USER_API_URL` from
|
|
36
|
-
variables; `pikku dev` sets it once the port is bound, and a stage's deployer sets it
|
|
37
|
-
there. A missing value fails the run naming the variable. The same variable works on
|
|
38
|
-
a dev machine, a node box and a Worker.
|
|
39
|
-
|
|
40
|
-
**What this rules out:** a second sign-in route with its own checks, a credential that
|
|
41
|
-
is shared with, or derived for, a caller inside the app, and a bearer token handed
|
|
42
|
-
back to a run.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Virtual user sign-in is proven by Set-Cookie, not a non-empty jar
|
|
4
|
-
description: HttpVirtualUser tracks its own signedIn flag and both VirtualUserSignIn implementations require the sign-in response itself to set a cookie, because a populated jar proves nothing
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Virtual user sign-in is proven by Set-Cookie, not a non-empty jar
|
|
9
|
-
|
|
10
|
-
`HttpVirtualUser` (`packages/core/src/services/http-virtual-users.ts`) keeps a
|
|
11
|
-
private `signedIn` boolean rather than inferring the session from its cookie
|
|
12
|
-
jar. Both `VirtualUserSignIn` implementations in
|
|
13
|
-
`packages/core/src/services/virtual-user-sign-in.ts` — `statementSignIn` and
|
|
14
|
-
`inProcessSignIn` — throw when the sign-in response carries no `Set-Cookie`
|
|
15
|
-
header, even though the response was a 2xx.
|
|
16
|
-
|
|
17
|
-
A cookie jar cannot answer "did sign-in happen". A target app may set a cookie on
|
|
18
|
-
any request — a CSRF token, an anonymous session, a locale — so a non-empty jar
|
|
19
|
-
after a failed or skipped sign-in looks exactly like a successful one. What
|
|
20
|
-
actually proves a session was established is _this_ response setting a cookie. A
|
|
21
|
-
2xx alone is not enough either: an endpoint that returns 200 while quietly
|
|
22
|
-
declining to issue a session would leave the virtual user running every subsequent
|
|
23
|
-
request unauthenticated, and the scenario would report the resulting refusals as
|
|
24
|
-
genuine permission failures.
|
|
25
|
-
|
|
26
|
-
**What this rules out:** replacing `signedIn` with a `jar.isEmpty()` check,
|
|
27
|
-
dropping the `getSetCookie().length === 0` guard as redundant with `res.ok`, and
|
|
28
|
-
treating `signOut()` as jar-clearing only — it must reset the flag too, or the
|
|
29
|
-
next call proceeds believing it has a session.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Virtual user sign-in only works for virtual-user-flagged users
|
|
4
|
-
description: A virtual user statement mints sessions for user rows flagged virtual user and nothing else, so holding one never impersonates a real user
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Virtual user sign-in only works for virtual-user-flagged users
|
|
9
|
-
|
|
10
|
-
A statement or an in-process call signs in only user rows flagged `virtualUser: true`
|
|
11
|
-
(see [virtual user sign-in has one door](virtual-user-sign-in-has-one-door.md)). That
|
|
12
|
-
could look like a master key, and it deliberately is not one — for two independent
|
|
13
|
-
reasons.
|
|
14
|
-
|
|
15
|
-
The first is the flag. The Better Auth virtual user plugin upserts and signs in only
|
|
16
|
-
rows flagged `virtualUser: true`. A statement naming a real customer's address does not
|
|
17
|
-
mint that customer's session — it is refused. The flag also flows into the minted
|
|
18
|
-
session, so audits and analytics can tell scenario traffic from human traffic.
|
|
19
|
-
|
|
20
|
-
The second is that a statement names one virtual user: `sub` must be a declared virtual
|
|
21
|
-
user, and it expires and is accepted once — see
|
|
22
|
-
[an external caller presents one signed statement](an-external-virtual-user-caller-presents-one-signed-statement.md).
|
|
23
|
-
A leaked statement opens one synthetic account for a few minutes, not the population.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** widening the sign-in endpoint to accept any email "so
|
|
26
|
-
scenarios can test as a real user", and treating a statement as
|
|
27
|
-
equivalent to a session-signing key. It also rules out dropping the `virtualUser` flag
|
|
28
|
-
from the minted session — the audit trail's ability to separate synthetic from
|
|
29
|
-
real activity depends on it.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Webhook bodies are signed before they are enqueued
|
|
4
|
-
description: QueueWebhookService computes the HMAC at enqueue time so the signing key never travels in the queue payload
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Webhook bodies are signed before they are enqueued
|
|
9
|
-
|
|
10
|
-
`QueueWebhookService.prepareDelivery`
|
|
11
|
-
(`packages/core/src/services/queue-webhook-service.ts`) serialises the payload,
|
|
12
|
-
resolves the signing secret, computes the signature and writes it into the job's
|
|
13
|
-
`headers` — all before `queueService.add` is called. The worker,
|
|
14
|
-
`pikkuWebhookWorkerFunc`, POSTs headers it was handed and never sees a secret.
|
|
15
|
-
|
|
16
|
-
Signing in the worker instead would mean the key has to reach the worker, and the
|
|
17
|
-
only channel between the two is the queue payload: an SQS body, a Redis value, a
|
|
18
|
-
`jsonb` column, all of which are at rest, replicated, and visible to anyone who
|
|
19
|
-
can read the queue. The signature is not sensitive; the key is.
|
|
20
|
-
|
|
21
|
-
**What this rules out:** moving signing into the worker so it can re-sign on
|
|
22
|
-
retry, and putting `secret` (or a resolved key of any kind) onto `WebhookJobData`.
|
|
23
|
-
Note the related consequence: because the signature is fixed at enqueue time, a
|
|
24
|
-
key rotated between enqueue and delivery does not change an in-flight job's
|
|
25
|
-
signature — that is intended, not a bug to fix by carrying the key.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: wireAddon expose selects the RPC surface, and a list may widen it
|
|
4
|
-
description: The consuming app decides which addon functions rpc.exposed reaches per instance — unset keeps the addon's own expose, false closes the instance, a list names exactly what is callable — and the deploy analyzer applies the same rule
|
|
5
|
-
tags: addon, rpc, expose, authorization
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# wireAddon expose selects the RPC surface, and a list may widen it
|
|
9
|
-
|
|
10
|
-
`rpc.exposed('<name>:<fn>')` — what the generated `POST /rpc/:rpcName` forwards
|
|
11
|
-
to — used to consult only the addon's own `expose: true`. The app installing the
|
|
12
|
-
addon had no say: it could not close an addon whose author marked functions
|
|
13
|
-
exposed, and it could not open one the author had not. `mcp` already worked the
|
|
14
|
-
other way (the wiring decides), and the two now match.
|
|
15
|
-
|
|
16
|
-
`expose` on `wireAddon` is `boolean | string[]`, resolved per instance by
|
|
17
|
-
`isAddonFunctionExposed`:
|
|
18
|
-
|
|
19
|
-
- **unset or `true`** — the addon's declaration decides, as before. Keeping the
|
|
20
|
-
default unchanged means no existing app gains or loses a route on upgrade.
|
|
21
|
-
- **`false`** — nothing in this instance is reachable through `rpc.exposed`.
|
|
22
|
-
- **a list** — exactly those functions, whether or not the addon declared them.
|
|
23
|
-
The list can widen the addon's surface, the same power `mcp` has, because the
|
|
24
|
-
app is the one that knows what its deployment should offer. The generated
|
|
25
|
-
`#pikku/addon` types the list against the package's function names, and a name
|
|
26
|
-
that survives to the build unpublished fails it with PKU343.
|
|
27
|
-
The value has to be written inline (`true`, `false` or an array of string
|
|
28
|
-
literals): the build reads it statically, and a variable or spread fails it
|
|
29
|
-
with PKU344 rather than being read as unset, which would leave the deploy
|
|
30
|
-
units disagreeing with the runtime.
|
|
31
|
-
|
|
32
|
-
The decision is per **instance**, not per package: two `wireAddon` calls for one
|
|
33
|
-
package may expose different things, and the gate reads the config the
|
|
34
|
-
namespace resolved to.
|
|
35
|
-
|
|
36
|
-
The deploy analyzer's per-addon unit applies the same rule, since that unit is
|
|
37
|
-
what the dispatcher can forward to. A function the wiring refuses gets no unit
|
|
38
|
-
and no dispatch entry, so the `deploymentService` fallback in `rpc.exposed` —
|
|
39
|
-
which forwards namespaced names with no local metadata — has nothing to reach.
|
|
40
|
-
Where the dispatcher does hold the wiring, it also refuses locally before
|
|
41
|
-
forwarding.
|
|
42
|
-
|
|
43
|
-
`expose` is reachability, not authorization. A listed function still runs
|
|
44
|
-
through `runPikkuFunc` with its own `auth`, permissions and the instance's
|
|
45
|
-
`auth`/`scopes`/`tags` — see
|
|
46
|
-
[addon auth and tags](./addon-auth-and-tags-only-tighten.md). Widening the list
|
|
47
|
-
to a sessionless function makes it public unless one of those gates it.
|
|
48
|
-
|
|
49
|
-
**What this rules out:** letting the addon's `expose: true` override a wiring's
|
|
50
|
-
`false`; treating an unknown list entry as a silent no-op; and a deploy unit
|
|
51
|
-
that carries functions the runtime gate would refuse.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: An approval decision is stored raw and validated on replay, and an invalid one closes the gate rather than failing the run
|
|
4
|
-
description: The schema only exists inside the workflow body, and letting an external payload fail the run would let any caller kill a workflow
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# An approval decision is stored raw and validated on replay, and an invalid one closes the gate rather than failing the run
|
|
9
|
-
|
|
10
|
-
`approveStep` in `pikku-workflow-service.ts` is called from outside the workflow
|
|
11
|
-
— an HTTP route, an RPC — where the approval's schema value is not in scope. It
|
|
12
|
-
therefore stores the decision payload raw in run state and does nothing else.
|
|
13
|
-
Validation happens on replay inside `approvalStep`, in the workflow body, which
|
|
14
|
-
is the only place the schema exists.
|
|
15
|
-
|
|
16
|
-
When validation fails, the bad decision is dropped, the issues are recorded on
|
|
17
|
-
the gate's state record, and a `WorkflowSuspendedException` re-closes the gate.
|
|
18
|
-
The failure stays legible to whoever tries next, and — the security point —
|
|
19
|
-
failing the run instead would let any caller kill a workflow with a malformed
|
|
20
|
-
payload. A later valid decision still lands normally.
|
|
21
|
-
|
|
22
|
-
`WorkflowApprovalOptions.schema` is a VALUE, not a type generic, for the same
|
|
23
|
-
reason: the payload arrives from an untrusted caller over the approve wire, and
|
|
24
|
-
a generic is erased at compile time, so it would validate nothing. Any
|
|
25
|
-
standard-schema library (zod, valibot, arktype) satisfies it. The contract is
|
|
26
|
-
the `~standard` spec and nothing more: `@pikku/core` deliberately carries no
|
|
27
|
-
zod dependency, which is why `pikku-workflow-service.test.ts` hand-rolls a
|
|
28
|
-
minimal `StandardSchemaV1` rather than importing a validation library.
|
|
29
|
-
|
|
30
|
-
A decision arriving for a gate that has already resolved is rejected with
|
|
31
|
-
`WorkflowApprovalResolvedError` (409) rather than accepted and dropped. The gate
|
|
32
|
-
caches its outcome as the step result and never re-reads run state, so a
|
|
33
|
-
decision recorded after resolution could not take effect — most obviously when
|
|
34
|
-
it loses the race with expiry — and the approver has to be told their decision
|
|
35
|
-
did not land.
|
|
36
|
-
|
|
37
|
-
**What this rules out:** validating in `approveStep` (the schema is not there),
|
|
38
|
-
failing the run on an invalid payload, turning `schema` into a type parameter,
|
|
39
|
-
accepting a decision on a resolved gate, or making a resolved gate re-read run
|
|
40
|
-
state so a late decision "wins".
|
package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Workflow helper functions are registered sessionless by declaration
|
|
4
|
-
description: Queue-worker helpers and the workflow sleeper get meta with sessionless true, so the runner requires a session for them only where their own auth flag says so
|
|
5
|
-
tags: core, workflow, queue, sessions
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Workflow helper functions are registered sessionless by declaration
|
|
9
|
-
|
|
10
|
-
`helperFunctionMeta` in `packages/core/src/wirings/workflow/workflow-queue-wiring.ts` returns the function meta for internal workflow helpers. It sets `sessionless: true` and `functionType: 'helper'`, and sets no `expose` flag (`workflow-queue-wiring.ts:19-25`).
|
|
11
|
-
|
|
12
|
-
It is applied to each queue worker function that has no meta yet (`workflow-queue-wiring.ts:66-68`), and to the built-in `pikkuWorkflowSleeper` (`workflow-queue-wiring.ts:122-129`).
|
|
13
|
-
|
|
14
|
-
With `sessionless` set, the runner requires a session only when the wiring, the function config, or the addon says `auth: true` (`packages/core/src/function/function-runner.ts:385-395`). The helpers therefore run without a session unless one of those says otherwise.
|
|
15
|
-
|
|
16
|
-
The helpers are internal. Their safety rests on the absence of `expose`, and on the scenario and workflow rules that keep such functions off the network surface ([scenario-step functions are never externally invocable](scenario-step-functions-are-never-externally-invocable.md)).
|
|
17
|
-
|
|
18
|
-
**What this rules out:** declaring a function that acts on a user's behalf as a workflow helper to skip its session requirement, and exposing a helper over RPC by adding `expose` to its meta.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A queued workflow step rehydrates its session from the persisted run wire
|
|
4
|
-
description: The queue job payload is just `{ runId }`, so without threading `pikkuUserId` an authed step sees no session and throws
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A queued workflow step rehydrates its session from the persisted run wire
|
|
9
|
-
|
|
10
|
-
A queued workflow step is executed with the bare job wire — the payload is just
|
|
11
|
-
`{ runId }` (or `{ runId, stepName, rpcName, data, fromStepName }`) — so it
|
|
12
|
-
carries no `pikkuUserId`. `invokeStepRpc` in `pikku-workflow-service.ts`
|
|
13
|
-
therefore merges the run's own `wire.pikkuUserId` into the step wire override
|
|
14
|
-
before calling `rpcWithWire`. Without it, a step written as an authed
|
|
15
|
-
`pikkuFunc` sees no session and fails with "Authentication required" on the
|
|
16
|
-
queued path while passing inline, which is the worst possible split: it looks
|
|
17
|
-
like a transport bug rather than an auth one.
|
|
18
|
-
|
|
19
|
-
`invokeStepRpc` is shared by the queue executor and the inline executor
|
|
20
|
-
precisely so the two cannot drift. The only thing that differs between
|
|
21
|
-
transports is who calls it, not the call itself. `createWorkflowWire` and
|
|
22
|
-
`runWorkflowJobInner` propagate the same `pikkuUserId` onto the workflow wire
|
|
23
|
-
for the workflow body.
|
|
24
|
-
|
|
25
|
-
The user id is the only identity carried. It is a reference for credential
|
|
26
|
-
resolution, not a serialized session — the session itself is rehydrated on the
|
|
27
|
-
far side.
|
|
28
|
-
|
|
29
|
-
**What this rules out:** giving the queued path its own invocation helper,
|
|
30
|
-
dropping the `pikkuUserId` merge because "the wire already has a session"
|
|
31
|
-
inline, or widening the run wire to persist session tokens instead of a user id
|
|
32
|
-
reference.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Scenario sessions are isolated per virtual user and reset between scenarios
|
|
4
|
-
description: One jar per virtual user keeps two virtual users from sharing a session; a browser reset keeps one scenario from leaving the next signed in as somebody else
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Scenario sessions are isolated per virtual user and reset between scenarios
|
|
9
|
-
|
|
10
|
-
`createCookieJar` in `services/scenario-cookie-jar.ts` holds its `Map` as a closure
|
|
11
|
-
local, so two jars can never share a session. That is precisely what lets one
|
|
12
|
-
scenario sign in as several people without one of them inheriting another's
|
|
13
|
-
session. Every response is read, not just the sign-in, so a cookie the target
|
|
14
|
-
rotates mid-session is followed rather than dropped, and an empty `Set-Cookie`
|
|
15
|
-
value is treated as a deletion — the name is dropped rather than held as a
|
|
16
|
-
cookie whose value says it is gone. The jar also stamps `Origin`, because Better
|
|
17
|
-
Auth rejects a state-changing POST whose Origin does not match its baseURL.
|
|
18
|
-
|
|
19
|
-
`ScenarioCookieJar.empty` reports a fact about the jar, not about the session: a
|
|
20
|
-
target that sets a CSRF or locale cookie before anyone signs in fills the jar
|
|
21
|
-
without establishing a session. Anything needing to know whether a sign-in
|
|
22
|
-
happened has to track the sign-in itself.
|
|
23
|
-
|
|
24
|
-
The browser side has the same requirement. `ScenarioBrowserProvider.reset`
|
|
25
|
-
discards every virtual user's per-scenario state — cookies, storage, open pages — while
|
|
26
|
-
keeping the browser, and is called between scenarios so one scenario cannot
|
|
27
|
-
leave the next signed in as somebody else.
|
|
28
|
-
|
|
29
|
-
**What this rules out:** hoisting the jar to a module-level or per-service map,
|
|
30
|
-
sharing one jar across virtual users, reading `Set-Cookie` only from the sign-in
|
|
31
|
-
response, treating `empty === false` as "signed in", or skipping `reset` between
|
|
32
|
-
scenarios as an optimisation.
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scenario step is never registered as a callable RPC and never dispatched on the queue
|
|
4
|
-
description: A step drives a browser and holds a virtual user's session, so exposing it as an RPC would put that reach on the network
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scenario step is never registered as a callable RPC and never dispatched on the queue
|
|
9
|
-
|
|
10
|
-
`ScenarioStepMeta` in `dsl/workflow-dsl.types.ts` is a distinct meta type from
|
|
11
|
-
`RpcStepMeta` on purpose. A scenario step runs locally through `runPikkuFunc`
|
|
12
|
-
and must never be treated as dispatchable on the queue or replay path, nor
|
|
13
|
-
registered as a callable RPC — a browser-driving step must not be
|
|
14
|
-
network-invocable. It executes with a browser handle and a virtual user's
|
|
15
|
-
authenticated session in hand; exposed as an RPC it would hand a remote caller
|
|
16
|
-
that reach.
|
|
17
|
-
|
|
18
|
-
`PikkuScenarioService.scenarioStep` reflects this at runtime: it always runs
|
|
19
|
-
through `engine.inlineStep` with `runPikkuFunc`, never through `rpcStep`, so no
|
|
20
|
-
transport is involved. A step declaring `browser: true` is refused outright
|
|
21
|
-
unless both a browser provider is registered and a virtual user was supplied, with an
|
|
22
|
-
error saying which is missing.
|
|
23
|
-
|
|
24
|
-
Scenario steps are also modelled as sessionless pikku functions (see
|
|
25
|
-
`scenario-step.test.ts`) because a step is driven by a virtual user, not by a wire
|
|
26
|
-
session.
|
|
27
|
-
|
|
28
|
-
**What this rules out:** collapsing `ScenarioStepMeta` into `RpcStepMeta`,
|
|
29
|
-
registering step functions in the RPC map so they "can be tested directly",
|
|
30
|
-
routing a scenario step through `rpcStep`/`dispatchStep`, or defaulting a
|
|
31
|
-
`browser: true` step to run without a virtual user.
|
package/knowledge/decisions/security/workflow-virtual-user-steps-always-use-the-real-transport.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: A scenario virtual user step always goes over the real transport and never through internal dispatch
|
|
4
|
-
description: Internal dispatch would bypass auth middleware and permissions, turning a scenario into a green health check that proves nothing
|
|
5
|
-
tags: workflow
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A scenario virtual user step always goes over the real transport and never through internal dispatch
|
|
9
|
-
|
|
10
|
-
When a workflow step carries `options.virtualUser`, `rpcStep` in
|
|
11
|
-
`pikku-workflow-service.ts` calls `virtualUser.invoke(rpcName, data)` — the virtual user's
|
|
12
|
-
authenticated client, over the real network transport — and never falls back to
|
|
13
|
-
internal dispatch. Internal dispatch skips auth middleware and permission
|
|
14
|
-
checks, so a scenario that "passed" that way would prove only that the function
|
|
15
|
-
body runs, not that the virtual user is allowed to run it. That is a green health
|
|
16
|
-
check for a system that may be wide open.
|
|
17
|
-
|
|
18
|
-
For the same reason, virtual user steps never queue: `rpcStep` short-circuits
|
|
19
|
-
`dispatchStep` to `false` whenever `options.virtualUser` is set. A virtual user step is an
|
|
20
|
-
outbound HTTP call made by the runner itself, and the virtual user's session lives in
|
|
21
|
-
this process — a queued worker in another process would have no session to make
|
|
22
|
-
it with. The step is still recorded durably like any RPC step, so replay and
|
|
23
|
-
reporting are unaffected.
|
|
24
|
-
|
|
25
|
-
Virtual user identity is process-local by nature. `PikkuScenarioService.runVirtualUsers` maps
|
|
26
|
-
run id to live authenticated clients (cookie jars), and those ride that map
|
|
27
|
-
only, never the persisted run wire — a serialized session on a durable run row
|
|
28
|
-
would be a credential at rest.
|
|
29
|
-
|
|
30
|
-
**What this rules out:** adding an "internal dispatch is faster" fast path for
|
|
31
|
-
virtual user steps, routing a virtual user step through the queue, serializing virtual user sessions
|
|
32
|
-
onto the run wire, or letting `virtualUser.invoke` degrade to `rpcWithWire` when the
|
|
33
|
-
transport is unavailable. Each turns an end-to-end authorization test into one
|
|
34
|
-
that cannot fail.
|
package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Writing a virtual user schedule is gated by its own scope, separate from running one
|
|
4
|
-
description: setVirtualUserSchedule carries virtualUser:schedule, because a schedule write spends money on every future tick while a run spends it once with a caller watching
|
|
5
|
-
tags: core, cli, virtual-users, scopes, security
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Writing a virtual user schedule is gated by its own scope, separate from running one
|
|
9
|
-
|
|
10
|
-
`packages/core/src/wirings/virtual-user/virtual-user-schedule-store.ts` defines the store that keeps a virtual user's cadence. Its SECURITY note says a written row "spends money on every future tick, without a caller present to see it happen", and that the scaffold therefore "gates writes behind a scope of their own" (`virtual-user-schedule-store.ts:60-63`). Reading findings is "a much smaller permission than deciding they should keep going" (`virtual-user-schedule-store.ts:62-63`).
|
|
11
|
-
|
|
12
|
-
The gate is generated by the CLI. `packages/cli/src/functions/wirings/virtual-user/serialize-virtual-user-functions.ts` emits `setVirtualUserSchedule` with `scopes: ['virtualUser:schedule']` (line 456), with a comment saying a run "spends money once with a caller present to see it, while writing a schedule spends it repeatedly with nobody there". `listVirtualUserSchedules` needs only `virtualUser:read` (line 477). The tests assert the scope in `virtual-user-functions.test.ts:66`.
|
|
13
|
-
|
|
14
|
-
A scheduled tick has no caller. It runs as the reserved `pikku-platform` principal, whose session carries only `virtualUser:run` (`packages/cli/src/functions/wirings/virtual-user/serialize-virtual-user-functions.ts:510-519`), so a tick can start a run and cannot write a schedule.
|
|
15
|
-
|
|
16
|
-
The store's own design is related. `claim` is a compare-and-set on `nextRunAt`, so two processes on the same cron cannot both dispatch the same virtual user (`virtual-user-schedule-store.ts:78-91`). Its doc says a second dispatch would mean "the same user acting twice over, at twice the budget" (`virtual-user-schedule-store.ts:82-86`).
|
|
17
|
-
|
|
18
|
-
**What this rules out:** letting a caller who can read runs also create or change a schedule, and treating a schedule write as the same permission as a run.
|
package/knowledge/index.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: overview
|
|
3
|
-
title: Knowledge
|
|
4
|
-
description: Why @pikku/core is built the way it is — the reasoning that used to live in comments
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Knowledge
|
|
8
|
-
|
|
9
|
-
Pikku's source says _what_ it does. These notes say _why_, for the handful of
|
|
10
|
-
choices where the code alone reads as arbitrary or, worse, reads as a mistake.
|
|
11
|
-
|
|
12
|
-
The rule that produced this directory: **reasoning never lives in code.** A
|
|
13
|
-
comment that restates the line below it is deleted. A comment that records a
|
|
14
|
-
decision — a constraint, a trade-off, a thing that was tried and failed — moves
|
|
15
|
-
here and gets a name, so it can be linked to and argued with.
|
|
16
|
-
|
|
17
|
-
Everything mechanical is generated or inspectable: the wirings, the schemas, the
|
|
18
|
-
meta files, the export surface. A note that repeats them is a copy that will
|
|
19
|
-
drift.
|
|
20
|
-
|
|
21
|
-
<!-- pikku:knowledge-index -->
|
|
22
|
-
- [decisions](decisions/index.md) — a rule that was chosen, and what it rules out
|
|
23
|
-
- [questions](questions/index.md) — something asked and not yet answered
|
|
24
|
-
<!-- /pikku:knowledge-index -->
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Does a bearer JWT with no identity claim count as a session?
|
|
4
|
-
description: The cookie middleware refuses an identity-less JWT, but authBearer sets whatever decode returns, so the two paths disagree
|
|
5
|
-
tags: core, auth, middleware
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Does a bearer JWT with no identity claim count as a session?
|
|
9
|
-
|
|
10
|
-
`authCookie` (`packages/core/src/middleware/auth-cookie.ts`) only sets a session
|
|
11
|
-
when `hasSessionIdentity` is true, meaning the decoded payload has a key that is
|
|
12
|
-
not a registered JWT claim. Its test comment says a JWT of an absent session
|
|
13
|
-
still decodes to a truthy `{ iat, exp }` that "the runner accepts", and it guards
|
|
14
|
-
against that.
|
|
15
|
-
|
|
16
|
-
`authBearer` (`packages/core/src/middleware/auth-bearer.ts`) has no such check.
|
|
17
|
-
In JWT mode it calls `jwtService.decode(bearerToken)` and calls `setSession` on
|
|
18
|
-
any truthy result. Its test only covers a `null` decode.
|
|
19
|
-
|
|
20
|
-
What is asked: should a bearer token that decodes to `{ iat, exp }` alone be
|
|
21
|
-
treated as anonymous, as the cookie path does, or as an authenticated session?
|
|
22
|
-
Current behaviour: it becomes the request session. Whether a signed token of that
|
|
23
|
-
shape can be minted is not checked in core, because the `JWTService`
|
|
24
|
-
implementation is not in this package.
|
package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: A channel's middleware list accepts bare factories that nothing ever resolves
|
|
4
|
-
description: CoreChannel.channelMiddleware admits CorePikkuChannelMiddlewareFactory, but no runner calls one, so a bare factory would stall the chain
|
|
5
|
-
tags: core, channel
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# A channel's middleware list accepts bare factories that nothing resolves
|
|
9
|
-
|
|
10
|
-
`CoreChannel.channelMiddleware` is typed as
|
|
11
|
-
`(CorePikkuChannelMiddleware | CorePikkuChannelMiddlewareFactory)[]`, but
|
|
12
|
-
`runPikkuFunc`'s `wireChannelMiddleware` parameter admits only
|
|
13
|
-
`CorePikkuChannelMiddleware[]`. The two call sites that bridge them —
|
|
14
|
-
`channel-common.ts` and `channel-handler.ts` — assert across the gap.
|
|
15
|
-
|
|
16
|
-
A factory is `(input: In) => CorePikkuChannelMiddleware`: the author is meant to
|
|
17
|
-
_call_ it at wiring time and put the result in the array.
|
|
18
|
-
`combineChannelMiddleware` contains no factory-resolution branch, and neither
|
|
19
|
-
does `combineMiddleware` for ordinary middleware — that is consistent and
|
|
20
|
-
deliberate. So a bare, uncalled factory in `channelMiddleware` would be pushed
|
|
21
|
-
into the chain and then invoked as if it were middleware: it would receive
|
|
22
|
-
`(services, channel, next)` as its single `input` argument, return a middleware
|
|
23
|
-
function that nothing runs, and never call `next` — stalling the chain silently.
|
|
24
|
-
|
|
25
|
-
Nothing in this repository puts a bare factory there, so the failure is
|
|
26
|
-
hypothetical today. The type is what invites it.
|
|
27
|
-
|
|
28
|
-
**What would settle it:** deciding whether `channelMiddleware` should accept
|
|
29
|
-
only resolved middleware — in which case the union is simply wrong and should
|
|
30
|
-
lose its factory arm, and both assertions disappear — or whether the runner
|
|
31
|
-
should resolve factories, in which case `combineChannelMiddleware` needs a
|
|
32
|
-
branch and the ordinary middleware path probably needs the matching one.
|
|
33
|
-
|
|
34
|
-
Until then the assertions name the exact target type rather than `as any`, so
|
|
35
|
-
the gap is visible at both call sites.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Can dev quick login become impersonation?
|
|
4
|
-
description: Dev quick login signs in a fixed admin account; making it an impersonation step needs an existing admin session it does not have, so it would need a new bypass
|
|
5
|
-
tags: auth, services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Can dev quick login become impersonation?
|
|
9
|
-
|
|
10
|
-
Today `/dev/quick-login` (`packages/services/better-auth/src/dev-quick-login.ts`)
|
|
11
|
-
provisions a fixed `admin@pikku.dev` account with a fixed password and grants it
|
|
12
|
-
the admin and console roots. It is refused outside loopback, behind a proxy, and
|
|
13
|
-
in production.
|
|
14
|
-
|
|
15
|
-
The proposal is that quick login should just be impersonation. Impersonation
|
|
16
|
-
(`resolveImpersonatedSession`) only applies on top of an existing session, and
|
|
17
|
-
the caller must hold `admin:impersonate`. Quick login has no session before it
|
|
18
|
-
runs, so making it impersonation needs one of:
|
|
19
|
-
|
|
20
|
-
- an unauthenticated dev-only route that accepts a user id, which is a new
|
|
21
|
-
bypass of the check that impersonation exists to keep, or
|
|
22
|
-
- quick login keeps minting the dev admin session, and virtual users are
|
|
23
|
-
impersonated from there.
|
|
24
|
-
|
|
25
|
-
The second keeps one mechanism for virtual users. Undecided.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Does a delayed RPC run as the session it was scheduled with?
|
|
4
|
-
description: The in-memory scheduler stores the session it is given and returns it from getTask, but the delayed run invokes the RPC with no session
|
|
5
|
-
tags: core, scheduler, sessions
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Does a delayed RPC run as the session it was scheduled with?
|
|
9
|
-
|
|
10
|
-
The contract takes an optional session. `SchedulerService.scheduleRPC` in
|
|
11
|
-
`packages/core/src/services/scheduler-service.ts:19-24` accepts `session`, and
|
|
12
|
-
`ScheduledTaskInfo` exposes it (`:9-13`).
|
|
13
|
-
|
|
14
|
-
The in-memory implementation in `packages/schedule/src/in-memory-scheduler-service.ts`
|
|
15
|
-
accepts it (`:41-46`), stores it on the delayed task (`:85-92`), and returns it from
|
|
16
|
-
`getTask` (`:107-118`). The timer callback runs `rpc.invoke(rpcName, data)` on a
|
|
17
|
-
context built with an empty wire (`:69-75`). The session is not passed to that
|
|
18
|
-
call, and the file does not read it on the run path.
|
|
19
|
-
|
|
20
|
-
The comment at `:67-68` says the BullMQ and pg-boss schedulers enqueue
|
|
21
|
-
`{ rpcName, data, session }` and invoke the RPC with it. This file does not do so.
|
|
22
|
-
The caller in the workflow sleeper passes no session (`packages/core/src/wirings/workflow/pikku-workflow-service.ts:852-856`).
|
|
23
|
-
|
|
24
|
-
**Question:** should a delayed RPC run under the session captured at scheduling
|
|
25
|
-
time, as the comment describes for the other schedulers, or run with none? The
|
|
26
|
-
code stores the session, reports it, and does not use it.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Can a user id containing a colon read another user's credentials?
|
|
4
|
-
description: LocalCredentialService joins user id and name with a colon and matches users by prefix, so an id containing a colon may collide with another user's keys
|
|
5
|
-
tags: core, credentials, local-dev, isolation
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Can a user id containing a colon read another user's credentials?
|
|
9
|
-
|
|
10
|
-
`packages/core/src/services/local-credential-service.ts` stores each credential
|
|
11
|
-
under the key `userId:name`, or just `name` when there is no user
|
|
12
|
-
(`local-credential-service.ts:6-8`).
|
|
13
|
-
|
|
14
|
-
`getAll(userId)` returns every key that starts with `${userId}:`, and strips that
|
|
15
|
-
prefix to get the credential name (`local-credential-service.ts:31-39`). If one
|
|
16
|
-
user's id contains a colon, its keys also start with the prefix of the id before
|
|
17
|
-
the colon. For example, user `a` would list the key of user `a:b`, credential `c`
|
|
18
|
-
(stored as `a:b:c`), under the name `b:c`.
|
|
19
|
-
|
|
20
|
-
`getUsersWithCredential` (`local-credential-service.ts:42-51`) and `getAllUsers`
|
|
21
|
-
(`local-credential-service.ts:53-62`) both split on the first colon, so they would
|
|
22
|
-
report user `a:b` as `a`.
|
|
23
|
-
|
|
24
|
-
Nothing in this file validates a user id. What is asked: can a user id contain a
|
|
25
|
-
colon in practice? If it can, is a user with id `a` meant to see keys belonging
|
|
26
|
-
to `a:b`? The code currently allows it, and no comment or test in this file says
|
|
27
|
-
which is intended.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Does a wireCLI command need a session when it sets no auth?
|
|
4
|
-
description: The channel default is documented as requiring a session, but a CLI command has no default of its own; its session need comes from whether the function is sessionless
|
|
5
|
-
tags: core, cli, auth
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Does a wireCLI command need a session when it sets no auth?
|
|
9
|
-
|
|
10
|
-
For channels, an absent `auth` requires a session. `packages/core/src/wirings/channel/channel.types.ts:67-76`
|
|
11
|
-
and `packages/core/src/wirings/channel/channel-runner.ts:142` both say so.
|
|
12
|
-
|
|
13
|
-
`wireCLI` in `packages/core/src/wirings/cli/cli-runner.ts` copies `auth` and
|
|
14
|
-
`permissions` from the function (`:89-90`, `:105`). It merges a command-level
|
|
15
|
-
`auth` onto the registration as `commandAuth ?? existing.auth` (`:176`, `:190`,
|
|
16
|
-
`:201`). No default is set anywhere in that path.
|
|
17
|
-
|
|
18
|
-
When the command runs, `runPikkuFunc` is called with `auth: false` (`:393-397`).
|
|
19
|
-
In `packages/core/src/function/function-runner.ts:385-404`, a sessionless function
|
|
20
|
-
requires a session only when the wiring or the function sets `auth: true` (`:386-392`).
|
|
21
|
-
A function that is not sessionless always requires one and throws when there is none
|
|
22
|
-
(`:401-403`). `auth: false` on such a function only logs a warning (`:396-400`).
|
|
23
|
-
|
|
24
|
-
**Question:** should a CLI command with no `auth` require a session as a channel
|
|
25
|
-
does? The code does not set that default for CLI commands. Whether a command needs
|
|
26
|
-
one depends on whether the function is declared sessionless.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: question
|
|
3
|
-
title: Does an adversarial user's in-scope success count as a finding?
|
|
4
|
-
description: The disposition doc says a 2xx is a finding for an inverted oracle, but the engine only flags successes outside the virtual user's scopes, and in-scope 2xx depends on the app's classifier
|
|
5
|
-
tags: core, virtual-user, authorization
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Does an adversarial user's in-scope success count as a finding?
|
|
9
|
-
|
|
10
|
-
`dispositionProfile` in `packages/core/src/wirings/virtual-user/virtual-user-dispositions.ts`
|
|
11
|
-
documents `invertedOracle` as meaning "a 2xx is a finding rather than a success".
|
|
12
|
-
The comment on the field says the engine "flags the success and leaves ownership
|
|
13
|
-
to the app's classifier".
|
|
14
|
-
|
|
15
|
-
In `run-virtual-user.ts` the flag does one thing: at line 302 it drops the
|
|
16
|
-
scope narrowing, so an adversarial user is offered the whole catalogue. The
|
|
17
|
-
finding that fires on a 2xx is the `unexpected-success` check around lines
|
|
18
|
-
627-645. It requires `response.ok` and a scope the virtual user does not hold. A
|
|
19
|
-
2xx on an endpoint the virtual user is entitled to produces no engine finding. Only the
|
|
20
|
-
app's `classify` hook can flag it, and that is the ownership check the comment
|
|
21
|
-
describes.
|
|
22
|
-
|
|
23
|
-
So the flag's name and doc describe a stronger oracle than the engine applies.
|
|
24
|
-
What is asked: should `invertedOracle` make every 2xx a finding in the engine, as
|
|
25
|
-
its doc says, or is the classifier meant to be the only place a 2xx becomes a
|
|
26
|
-
finding, with the doc corrected?
|