@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,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges the credential declarations the inspector found into meta keyed by name.
|
|
3
|
+
* A name declared more than once must agree on type and schema.
|
|
4
|
+
*
|
|
5
|
+
* @throws Error when two declarations of one name disagree on `type` or schema.
|
|
6
|
+
* @internal Called by the CLI when generating meta.
|
|
7
|
+
*/
|
|
1
8
|
export function validateAndBuildCredentialDefinitionsMeta(definitions, schemaLookup) {
|
|
2
9
|
const meta = {};
|
|
3
10
|
for (const def of definitions) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FeatureFlagSource } from '../../services/feature-flag-service.js';
|
|
2
2
|
import type { DeclaredFlag, FlagConfigSnapshot } from './flag.types.js';
|
|
3
|
+
/** Tuning for a {@link CachedFlagSource}. */
|
|
3
4
|
export interface CachedFlagSourceOptions {
|
|
4
5
|
/**
|
|
5
6
|
* How long a snapshot is served before it is refreshed, in milliseconds.
|
|
@@ -33,13 +33,16 @@ export type CoreFeatureFlag = {
|
|
|
33
33
|
* like a scope id invites exactly the confusion this exists to prevent.
|
|
34
34
|
*/
|
|
35
35
|
export type CoreFeatureFlags = Record<string, CoreFeatureFlag>;
|
|
36
|
+
/** A feature flag declaration as recorded in generated meta. */
|
|
36
37
|
export type FeatureFlagDefinitionMeta = {
|
|
37
38
|
name: string;
|
|
38
39
|
description?: string;
|
|
39
40
|
anyOf?: string[];
|
|
40
41
|
sourceFile?: string;
|
|
41
42
|
};
|
|
43
|
+
/** Feature flag declarations as the inspector found them. */
|
|
42
44
|
export type FeatureFlagDefinitions = FeatureFlagDefinitionMeta[];
|
|
45
|
+
/** Feature flag declarations collected by the CLI, keyed by name. */
|
|
43
46
|
export type FeatureFlagDefinitionsMeta = Record<string, FeatureFlagDefinitionMeta>;
|
|
44
47
|
/** A declared flag, ready to sync into a flag store. */
|
|
45
48
|
export type DeclaredFlag = {
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import type { CoreGateway, GatewayAdapter } from './gateway.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a gateway's adapter, calling a factory adapter with the singleton services once and
|
|
4
|
+
* caching the promise per gateway config.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
2
7
|
export declare const resolveGatewayAdapter: (config: CoreGateway, services: CoreSingletonServices) => Promise<GatewayAdapter>;
|
|
3
8
|
import type { CoreSingletonServices } from '../../types/core.types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Wires a messaging gateway (Slack, WhatsApp, a web chat, ...) so each inbound message runs `func`
|
|
11
|
+
* with the adapter-normalised message.
|
|
12
|
+
*
|
|
13
|
+
* - `webhook` registers `POST <route>` (and `GET <route>` for adapters with `verifyWebhook`,
|
|
14
|
+
* answering the platform's challenge; a failed challenge is a 401).
|
|
15
|
+
* - `websocket` registers a channel at `route`; replies go back over the socket.
|
|
16
|
+
* - `listener` registers no route; `GatewayService.start()` opens the adapter outward.
|
|
17
|
+
*
|
|
18
|
+
* The routes themselves are unauthenticated, so verify the platform's signature in the gateway's
|
|
19
|
+
* `middleware`. That middleware runs before the function gate and may establish the session the
|
|
20
|
+
* handler's `auth` then checks. A non-empty `text`, `richContent` or `attachments` return value is
|
|
21
|
+
* sent back to the sender through the adapter.
|
|
22
|
+
*
|
|
23
|
+
* @param config - The gateway's name, transport, adapter and handler.
|
|
24
|
+
* @throws Error when `type` is unknown, or `route` is missing for `webhook`/`websocket`.
|
|
25
|
+
* @example snippet: gatewayWebsocket
|
|
26
|
+
*/
|
|
4
27
|
export declare const wireGateway: (config: CoreGateway) => void;
|
|
5
28
|
/** The returned callback is what a GatewayService passes to `adapter.init()`. */
|
|
6
29
|
export declare const createListenerMessageHandler: (name: string, config: CoreGateway, singletonServices: CoreSingletonServices) => ((rawData: unknown) => Promise<void>);
|
|
@@ -50,6 +50,11 @@ const registerGatewayHandler = (config) => {
|
|
|
50
50
|
* middleware group.
|
|
51
51
|
*/
|
|
52
52
|
const gatewayInheritedMiddleware = (config) => pikkuState(null, 'gateway', 'meta')[config.name]?.middleware;
|
|
53
|
+
/**
|
|
54
|
+
* Resolves a gateway's adapter, calling a factory adapter with the singleton services once and
|
|
55
|
+
* caching the promise per gateway config.
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
53
58
|
export const resolveGatewayAdapter = (config, services) => {
|
|
54
59
|
let resolved = resolvedAdapters.get(config);
|
|
55
60
|
if (!resolved) {
|
|
@@ -61,6 +66,24 @@ export const resolveGatewayAdapter = (config, services) => {
|
|
|
61
66
|
}
|
|
62
67
|
return resolved;
|
|
63
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Wires a messaging gateway (Slack, WhatsApp, a web chat, ...) so each inbound message runs `func`
|
|
71
|
+
* with the adapter-normalised message.
|
|
72
|
+
*
|
|
73
|
+
* - `webhook` registers `POST <route>` (and `GET <route>` for adapters with `verifyWebhook`,
|
|
74
|
+
* answering the platform's challenge; a failed challenge is a 401).
|
|
75
|
+
* - `websocket` registers a channel at `route`; replies go back over the socket.
|
|
76
|
+
* - `listener` registers no route; `GatewayService.start()` opens the adapter outward.
|
|
77
|
+
*
|
|
78
|
+
* The routes themselves are unauthenticated, so verify the platform's signature in the gateway's
|
|
79
|
+
* `middleware`. That middleware runs before the function gate and may establish the session the
|
|
80
|
+
* handler's `auth` then checks. A non-empty `text`, `richContent` or `attachments` return value is
|
|
81
|
+
* sent back to the sender through the adapter.
|
|
82
|
+
*
|
|
83
|
+
* @param config - The gateway's name, transport, adapter and handler.
|
|
84
|
+
* @throws Error when `type` is unknown, or `route` is missing for `webhook`/`websocket`.
|
|
85
|
+
* @example snippet: gatewayWebsocket
|
|
86
|
+
*/
|
|
64
87
|
export const wireGateway = (config) => {
|
|
65
88
|
pikkuState(null, 'gateway', 'gateways').set(config.name, config);
|
|
66
89
|
switch (config.type) {
|
|
@@ -68,6 +68,7 @@ export interface GatewayAdapter {
|
|
|
68
68
|
/** Receives the GET query params, or the POST body when called from the POST handler. */
|
|
69
69
|
verifyWebhook?(data: unknown, request?: PikkuHTTPRequest): WebhookVerificationResult | Promise<WebhookVerificationResult>;
|
|
70
70
|
}
|
|
71
|
+
/** Builds a gateway adapter from the singleton services, for an adapter that needs a token or client. Called once per gateway. */
|
|
71
72
|
export type GatewayAdapterFactory = (services: CoreSingletonServices) => GatewayAdapter | Promise<GatewayAdapter>;
|
|
72
73
|
export interface PikkuGateway {
|
|
73
74
|
gatewayName: string;
|
|
@@ -77,6 +78,7 @@ export interface PikkuGateway {
|
|
|
77
78
|
}
|
|
78
79
|
/** 'webhook' the platform POSTs to us, 'websocket' the client connects to us, 'listener' no route at all. */
|
|
79
80
|
export type GatewayTransportType = 'webhook' | 'websocket' | 'listener';
|
|
81
|
+
/** The configuration `wireGateway` takes: transport, route, adapter, handler and middleware. */
|
|
80
82
|
export type CoreGateway<PikkuFunctionConfig = CorePikkuFunctionConfig<any, any>, PikkuMiddleware extends CorePikkuMiddleware = CorePikkuMiddleware> = Partial<Pick<CommonWireMeta, 'title' | 'summary' | 'description' | 'errors'>> & {
|
|
81
83
|
/** Unique across the project. It is how the gateway is addressed in `pikku meta` and in logs. */
|
|
82
84
|
name: string;
|
|
@@ -105,4 +107,5 @@ export type GatewayMeta = CommonWireMeta & {
|
|
|
105
107
|
auth?: boolean;
|
|
106
108
|
gateway: true;
|
|
107
109
|
};
|
|
110
|
+
/** Inspector-generated metadata for every wired gateway, keyed by name. */
|
|
108
111
|
export type GatewaysMeta = Record<string, GatewayMeta>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GatewayService } from '../../services/gateway-service.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-process `GatewayService` that starts every `listener` gateway's adapter and closes them on `stop()`.
|
|
4
|
+
* Assumes a single process: running it in several would open each listener more than once.
|
|
5
|
+
*/
|
|
6
|
+
export declare class LocalGatewayService implements GatewayService {
|
|
7
|
+
private activeAdapters;
|
|
8
|
+
start(): Promise<void>;
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { pikkuState, getSingletonServices } from '
|
|
2
|
-
import { createListenerMessageHandler, resolveGatewayAdapter, } from '
|
|
1
|
+
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
2
|
+
import { createListenerMessageHandler, resolveGatewayAdapter, } from './gateway-runner.js';
|
|
3
3
|
// knowledge: decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md
|
|
4
|
+
/**
|
|
5
|
+
* In-process `GatewayService` that starts every `listener` gateway's adapter and closes them on `stop()`.
|
|
6
|
+
* Assumes a single process: running it in several would open each listener more than once.
|
|
7
|
+
*/
|
|
4
8
|
export class LocalGatewayService {
|
|
5
9
|
activeAdapters = new Map();
|
|
6
10
|
async start() {
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import type { HTTPRouteMap, HTTPRouteContract, HTTPRoutesGroupConfig, WireHTTPRoutesConfig } from './http.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Declares a group of HTTP routes without wiring them, so the group can be composed and typed as a contract.
|
|
4
|
+
*
|
|
5
|
+
* Accepts either a bare route map or a config with `basePath`, `auth`, `tags`
|
|
6
|
+
* and `middleware` that apply to every route in it. Nested groups concatenate
|
|
7
|
+
* `basePath`s, tags and middleware; a route's own `auth` wins over the group's.
|
|
8
|
+
* Pass the result to {@link wireHTTPRoutes} to register it.
|
|
9
|
+
*
|
|
10
|
+
* @example snippet: wireHttp
|
|
11
|
+
*/
|
|
2
12
|
export declare function defineHTTPRoutes<T extends HTTPRouteMap>(routes: T): HTTPRouteContract<T>;
|
|
3
13
|
export declare function defineHTTPRoutes<T extends HTTPRouteMap>(config: HTTPRoutesGroupConfig & {
|
|
4
14
|
routes: T;
|
|
5
15
|
}): HTTPRouteContract<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Wires a map (or array) of routes and route groups in one call.
|
|
18
|
+
*
|
|
19
|
+
* Each route is registered through {@link wireHTTP} with its group's `basePath`
|
|
20
|
+
* prefixed to its path, the group's middleware run before its own, and the
|
|
21
|
+
* group's `auth` applied when the route sets none.
|
|
22
|
+
*
|
|
23
|
+
* @param config - Group options plus `routes`: a map of routes, groups from {@link defineHTTPRoutes}, or nested maps.
|
|
24
|
+
*
|
|
25
|
+
* @example snippet: httpRoutesWiring
|
|
26
|
+
*/
|
|
6
27
|
export declare const wireHTTPRoutes: (config: WireHTTPRoutesConfig) => void;
|
|
@@ -7,6 +7,17 @@ export function defineHTTPRoutes(configOrRoutes) {
|
|
|
7
7
|
}
|
|
8
8
|
return { routes: configOrRoutes };
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Wires a map (or array) of routes and route groups in one call.
|
|
12
|
+
*
|
|
13
|
+
* Each route is registered through {@link wireHTTP} with its group's `basePath`
|
|
14
|
+
* prefixed to its path, the group's middleware run before its own, and the
|
|
15
|
+
* group's `auth` applied when the route sets none.
|
|
16
|
+
*
|
|
17
|
+
* @param config - Group options plus `routes`: a map of routes, groups from {@link defineHTTPRoutes}, or nested maps.
|
|
18
|
+
*
|
|
19
|
+
* @example snippet: httpRoutesWiring
|
|
20
|
+
*/
|
|
10
21
|
export const wireHTTPRoutes = (config) => {
|
|
11
22
|
const { routes, ...groupConfig } = config;
|
|
12
23
|
if (Array.isArray(routes)) {
|
|
@@ -2,9 +2,80 @@ import type { CoreHTTPFunctionWiring, RunHTTPWiringOptions, PikkuHTTP, PikkuHTTP
|
|
|
2
2
|
import type { CorePikkuFunction, CorePikkuFunctionSessionless, CorePikkuPermission } from '../../function/functions.types.js';
|
|
3
3
|
import type { CorePikkuMiddleware, CorePikkuMiddlewareGroup } from '../../middleware/middleware.types.js';
|
|
4
4
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
5
|
+
/**
|
|
6
|
+
* Adds middleware that runs before every HTTP route whose path matches `pattern`.
|
|
7
|
+
*
|
|
8
|
+
* `'*'` matches every route, and is also what an unmatched `OPTIONS` request
|
|
9
|
+
* runs, so CORS middleware belongs there. Calling it again for the same pattern
|
|
10
|
+
* appends rather than replaces. Group middleware runs before a route's own
|
|
11
|
+
* `middleware` and before the permissions on its function.
|
|
12
|
+
*
|
|
13
|
+
* @param pattern - `'*'`, or a route prefix such as `'/orders'`.
|
|
14
|
+
* @param middleware - The middleware to add, in the order it should run.
|
|
15
|
+
* @param packageName - The addon package that owns the group; `null` for the app.
|
|
16
|
+
* @returns The `middleware` passed in, so a group can be declared and exported in one statement.
|
|
17
|
+
*
|
|
18
|
+
* @example snippet: httpMiddleware
|
|
19
|
+
*/
|
|
5
20
|
export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(pattern: string, middleware: CorePikkuMiddlewareGroup, packageName?: string | null) => CorePikkuMiddlewareGroup;
|
|
21
|
+
/**
|
|
22
|
+
* Wires a pikku function to one HTTP method and route.
|
|
23
|
+
*
|
|
24
|
+
* A route requires a session unless it sets `auth: false`, and an open route
|
|
25
|
+
* can only point at a sessionless function. Every `:param` in `route` must be a
|
|
26
|
+
* key of the function's input, which is checked at compile time. On a request
|
|
27
|
+
* the route's `headers` schema is validated first, then middleware, then the
|
|
28
|
+
* function's permissions, then the function itself; its return value is sent as
|
|
29
|
+
* JSON unless `returnsJSON` is `false` or it returns a `Response`.
|
|
30
|
+
*
|
|
31
|
+
* Registration needs the metadata `pikku` generates for the route. When none is
|
|
32
|
+
* found the wiring is skipped with a warning rather than throwing.
|
|
33
|
+
*
|
|
34
|
+
* @param httpWiring - The method, route, function and options for this route.
|
|
35
|
+
*
|
|
36
|
+
* @example snippet: httpSingleRoute
|
|
37
|
+
*/
|
|
6
38
|
export declare const wireHTTP: <In, Out, Route extends string, PikkuFunction extends CorePikkuFunction<In, Out> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out> = CorePikkuFunctionSessionless<In, Out>, PikkuPermissionGroup extends CorePikkuPermission<In> = CorePikkuPermission<In>, PikkuMiddleware extends CorePikkuMiddleware = CorePikkuMiddleware>(httpWiring: CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermissionGroup, PikkuMiddleware>) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Bundles a request and response into the `http` part of a wire, or `undefined` when neither is given.
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
7
43
|
export declare const createHTTPWire: (request: PikkuHTTPRequest | undefined, response: PikkuHTTPResponse | undefined) => PikkuHTTP | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Runs a web `Request` through the wired HTTP routes and returns a web `Response`.
|
|
46
|
+
*
|
|
47
|
+
* The entry point for fetch-based runtimes (Cloudflare Workers, Bun, Deno,
|
|
48
|
+
* Next.js route handlers). It uses the singleton services set by
|
|
49
|
+
* `setSingletonServices` / `pikkuState`, so they must be created first. Errors
|
|
50
|
+
* become JSON error responses rather than rejections, unless `bubbleErrors` is set.
|
|
51
|
+
*
|
|
52
|
+
* @param request - The incoming request. Its body is capped at `maxBodySize`
|
|
53
|
+
* bytes (default {@link DEFAULT_MAX_BODY_SIZE}); a larger body is answered with 413.
|
|
54
|
+
* @param params - Options for this request; see {@link RunHTTPWiringOptions}.
|
|
55
|
+
* @returns The response, including a 404 for an unmatched route and a 204 for an unmatched `OPTIONS`.
|
|
56
|
+
*/
|
|
8
57
|
export declare const fetch: <In, Out>(request: Request, params?: RunHTTPWiringOptions) => Promise<Response>;
|
|
58
|
+
/** Like {@link fetch}, but returns the {@link PikkuFetchHTTPResponse} so a host can read or adjust it before converting it to a web `Response`. */
|
|
9
59
|
export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest, params?: RunHTTPWiringOptions) => Promise<PikkuFetchHTTPResponse>;
|
|
60
|
+
/**
|
|
61
|
+
* Matches a request to a wired route, runs it, and writes the result into `response`.
|
|
62
|
+
*
|
|
63
|
+
* The lower-level form of {@link fetch} for adapters that bring their own
|
|
64
|
+
* request and response objects (Express, Fastify, uWS). A web `Request` is
|
|
65
|
+
* wrapped with the `maxBodySize` limit. The trace ID is taken from `traceId`,
|
|
66
|
+
* then the `x-request-id` header, then `generateRequestId`, and is returned to
|
|
67
|
+
* the client as `errorId` on failures.
|
|
68
|
+
*
|
|
69
|
+
* Errors are written to `response`: a 4xx keeps its message and payload, while a
|
|
70
|
+
* 5xx or an unknown error hides its message unless `exposeErrors` is set outside
|
|
71
|
+
* production. `exposeErrors` defaults to on outside production and is always off
|
|
72
|
+
* in production.
|
|
73
|
+
*
|
|
74
|
+
* @param request - A web `Request` or an adapter's {@link PikkuHTTPRequest}.
|
|
75
|
+
* @param response - Where the status, headers and body are written.
|
|
76
|
+
* @param options - See {@link RunHTTPWiringOptions}.
|
|
77
|
+
* @returns The function's return value, or `undefined` when the request failed or matched nothing.
|
|
78
|
+
* @throws The original error when `bubbleErrors` is set, after the error response has been written.
|
|
79
|
+
* @throws {Error} When `skipUserSession` is set on a route that requires auth.
|
|
80
|
+
*/
|
|
10
81
|
export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, exposeErrors, generateRequestId, traceId: externalTraceId, maxBodySize, }?: RunHTTPWiringOptions) => Promise<Out | void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NotFoundError } from '../../errors/errors.js';
|
|
2
2
|
import { createWeakUID, isSerializable } from '../../utils.js';
|
|
3
3
|
import { getSingletonServices, getCreateWireServices, } from '../../pikku-state.js';
|
|
4
|
-
import { PikkuSessionService } from '../../services/user-session-service.js';
|
|
4
|
+
import { PikkuSessionService, createMiddlewareSessionWireProps, } from '../../services/user-session-service.js';
|
|
5
5
|
import { getErrorResponse } from '../../errors/error-handler.js';
|
|
6
6
|
import { handleHTTPError } from '../../handle-error.js';
|
|
7
7
|
import { isProduction } from '../../env.js';
|
|
@@ -27,6 +27,21 @@ function extractHeadersFromRequest(request, headerKeys) {
|
|
|
27
27
|
}
|
|
28
28
|
return headers;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Adds middleware that runs before every HTTP route whose path matches `pattern`.
|
|
32
|
+
*
|
|
33
|
+
* `'*'` matches every route, and is also what an unmatched `OPTIONS` request
|
|
34
|
+
* runs, so CORS middleware belongs there. Calling it again for the same pattern
|
|
35
|
+
* appends rather than replaces. Group middleware runs before a route's own
|
|
36
|
+
* `middleware` and before the permissions on its function.
|
|
37
|
+
*
|
|
38
|
+
* @param pattern - `'*'`, or a route prefix such as `'/orders'`.
|
|
39
|
+
* @param middleware - The middleware to add, in the order it should run.
|
|
40
|
+
* @param packageName - The addon package that owns the group; `null` for the app.
|
|
41
|
+
* @returns The `middleware` passed in, so a group can be declared and exported in one statement.
|
|
42
|
+
*
|
|
43
|
+
* @example snippet: httpMiddleware
|
|
44
|
+
*/
|
|
30
45
|
export const addHTTPMiddleware = (pattern, middleware, packageName = null) => {
|
|
31
46
|
const httpGroups = pikkuState(packageName, 'middleware', 'httpGroup');
|
|
32
47
|
const existing = httpGroups[pattern];
|
|
@@ -35,6 +50,23 @@ export const addHTTPMiddleware = (pattern, middleware, packageName = null) => {
|
|
|
35
50
|
: middleware;
|
|
36
51
|
return middleware;
|
|
37
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Wires a pikku function to one HTTP method and route.
|
|
55
|
+
*
|
|
56
|
+
* A route requires a session unless it sets `auth: false`, and an open route
|
|
57
|
+
* can only point at a sessionless function. Every `:param` in `route` must be a
|
|
58
|
+
* key of the function's input, which is checked at compile time. On a request
|
|
59
|
+
* the route's `headers` schema is validated first, then middleware, then the
|
|
60
|
+
* function's permissions, then the function itself; its return value is sent as
|
|
61
|
+
* JSON unless `returnsJSON` is `false` or it returns a `Response`.
|
|
62
|
+
*
|
|
63
|
+
* Registration needs the metadata `pikku` generates for the route. When none is
|
|
64
|
+
* found the wiring is skipped with a warning rather than throwing.
|
|
65
|
+
*
|
|
66
|
+
* @param httpWiring - The method, route, function and options for this route.
|
|
67
|
+
*
|
|
68
|
+
* @example snippet: httpSingleRoute
|
|
69
|
+
*/
|
|
38
70
|
export const wireHTTP = (httpWiring) => {
|
|
39
71
|
const httpMeta = pikkuState(null, 'http', 'meta');
|
|
40
72
|
const routeMeta = httpMeta[httpWiring.method][httpWiring.route];
|
|
@@ -69,6 +101,10 @@ const getMatchingRoute = (requestType, requestPath) => {
|
|
|
69
101
|
};
|
|
70
102
|
}
|
|
71
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Bundles a request and response into the `http` part of a wire, or `undefined` when neither is given.
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
72
108
|
export const createHTTPWire = (request, response) => {
|
|
73
109
|
let http = undefined;
|
|
74
110
|
if (request || response) {
|
|
@@ -173,10 +209,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
173
209
|
traceId: requestId,
|
|
174
210
|
http,
|
|
175
211
|
channel,
|
|
176
|
-
|
|
177
|
-
setSession: (s) => userSession.setInitial(s),
|
|
178
|
-
getSession: () => userSession.get(),
|
|
179
|
-
hasSessionChanged: () => userSession.sessionChanged,
|
|
212
|
+
...createMiddlewareSessionWireProps(userSession),
|
|
180
213
|
};
|
|
181
214
|
const statusBeforeRoute = http?.response?.statusCode;
|
|
182
215
|
try {
|
|
@@ -233,16 +266,51 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
233
266
|
}
|
|
234
267
|
return { result };
|
|
235
268
|
};
|
|
269
|
+
/**
|
|
270
|
+
* Runs a web `Request` through the wired HTTP routes and returns a web `Response`.
|
|
271
|
+
*
|
|
272
|
+
* The entry point for fetch-based runtimes (Cloudflare Workers, Bun, Deno,
|
|
273
|
+
* Next.js route handlers). It uses the singleton services set by
|
|
274
|
+
* `setSingletonServices` / `pikkuState`, so they must be created first. Errors
|
|
275
|
+
* become JSON error responses rather than rejections, unless `bubbleErrors` is set.
|
|
276
|
+
*
|
|
277
|
+
* @param request - The incoming request. Its body is capped at `maxBodySize`
|
|
278
|
+
* bytes (default {@link DEFAULT_MAX_BODY_SIZE}); a larger body is answered with 413.
|
|
279
|
+
* @param params - Options for this request; see {@link RunHTTPWiringOptions}.
|
|
280
|
+
* @returns The response, including a 404 for an unmatched route and a 204 for an unmatched `OPTIONS`.
|
|
281
|
+
*/
|
|
236
282
|
export const fetch = async (request, params = {}) => {
|
|
237
283
|
const pikkuResponse = new PikkuFetchHTTPResponse();
|
|
238
284
|
await fetchData(request, pikkuResponse, params);
|
|
239
285
|
return pikkuResponse.toResponse();
|
|
240
286
|
};
|
|
287
|
+
/** Like {@link fetch}, but returns the {@link PikkuFetchHTTPResponse} so a host can read or adjust it before converting it to a web `Response`. */
|
|
241
288
|
export const pikkuFetch = async (request, params = {}) => {
|
|
242
289
|
const pikkuResponse = new PikkuFetchHTTPResponse();
|
|
243
290
|
await fetchData(request, pikkuResponse, params);
|
|
244
291
|
return pikkuResponse;
|
|
245
292
|
};
|
|
293
|
+
/**
|
|
294
|
+
* Matches a request to a wired route, runs it, and writes the result into `response`.
|
|
295
|
+
*
|
|
296
|
+
* The lower-level form of {@link fetch} for adapters that bring their own
|
|
297
|
+
* request and response objects (Express, Fastify, uWS). A web `Request` is
|
|
298
|
+
* wrapped with the `maxBodySize` limit. The trace ID is taken from `traceId`,
|
|
299
|
+
* then the `x-request-id` header, then `generateRequestId`, and is returned to
|
|
300
|
+
* the client as `errorId` on failures.
|
|
301
|
+
*
|
|
302
|
+
* Errors are written to `response`: a 4xx keeps its message and payload, while a
|
|
303
|
+
* 5xx or an unknown error hides its message unless `exposeErrors` is set outside
|
|
304
|
+
* production. `exposeErrors` defaults to on outside production and is always off
|
|
305
|
+
* in production.
|
|
306
|
+
*
|
|
307
|
+
* @param request - A web `Request` or an adapter's {@link PikkuHTTPRequest}.
|
|
308
|
+
* @param response - Where the status, headers and body are written.
|
|
309
|
+
* @param options - See {@link RunHTTPWiringOptions}.
|
|
310
|
+
* @returns The function's return value, or `undefined` when the request failed or matched nothing.
|
|
311
|
+
* @throws The original error when `bubbleErrors` is set, after the error response has been written.
|
|
312
|
+
* @throws {Error} When `skipUserSession` is set on a route that requires auth.
|
|
313
|
+
*/
|
|
246
314
|
export const fetchData = async (request, response, { skipUserSession = false, respondWith404 = true, logWarningsForStatusCodes = [], coerceDataFromSchema = true, bubbleErrors = false, exposeErrors = !isProduction(), generateRequestId, traceId: externalTraceId, maxBodySize, } = {}) => {
|
|
247
315
|
const singletonServices = getSingletonServices();
|
|
248
316
|
const createWireServices = getCreateWireServices();
|
|
@@ -4,12 +4,24 @@ import type { CommonWireMeta } from '../../types/core.types.js';
|
|
|
4
4
|
import type { CorePikkuMiddleware } from '../../middleware/middleware.types.js';
|
|
5
5
|
import type { CorePikkuFunction, CorePikkuFunctionSessionless, CorePikkuPermission, CorePikkuFunctionConfig } from '../../function/functions.types.js';
|
|
6
6
|
type ExtractHTTPWiringParams<S extends string> = S extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractHTTPWiringParams<`/${Rest}`> : S extends `${string}:${infer Param}` ? Param : never;
|
|
7
|
+
/** Resolves to `unknown` when every `:param` in a route is a key of `In`, and to a descriptive error tuple otherwise, so a mismatch fails to compile. */
|
|
7
8
|
export type AssertHTTPWiringParams<In, HTTPWiring extends string> = ExtractHTTPWiringParams<HTTPWiring> extends keyof In ? unknown : [
|
|
8
9
|
'Error: HTTPWiring parameters',
|
|
9
10
|
ExtractHTTPWiringParams<HTTPWiring>,
|
|
10
11
|
'not in',
|
|
11
12
|
keyof In
|
|
12
13
|
];
|
|
14
|
+
/**
|
|
15
|
+
* Per-request options for {@link fetch} and {@link fetchData}.
|
|
16
|
+
*
|
|
17
|
+
* - `skipUserSession` – do not resolve a session; throws for a route that requires auth.
|
|
18
|
+
* - `respondWith404` – write a 404 for an unmatched route (default `true`); `false` lets the host fall through to its own handlers.
|
|
19
|
+
* - `logWarningsForStatusCodes` – error statuses to log as warnings.
|
|
20
|
+
* - `coerceDataFromSchema` – coerce query and path strings to the schema's types (default `true`).
|
|
21
|
+
* - `bubbleErrors` – rethrow after writing the error response.
|
|
22
|
+
* - `exposeErrors` – include messages and stacks of 5xx errors; ignored in production.
|
|
23
|
+
* - `generateRequestId` – produce a trace ID when neither `traceId` nor `x-request-id` is present.
|
|
24
|
+
*/
|
|
13
25
|
export type RunHTTPWiringOptions = Partial<{
|
|
14
26
|
skipUserSession: boolean;
|
|
15
27
|
respondWith404: boolean;
|
|
@@ -23,8 +35,10 @@ export type RunHTTPWiringOptions = Partial<{
|
|
|
23
35
|
/** Maximum request body size in bytes, applied when pikku wraps a fetch `Request`. */
|
|
24
36
|
maxBodySize: number;
|
|
25
37
|
}>;
|
|
38
|
+
/** The HTTP methods a route can be wired to, in lower case. */
|
|
26
39
|
export type HTTPMethod = 'post' | 'get' | 'delete' | 'patch' | 'head' | 'put' | 'options';
|
|
27
40
|
export type HTTPHeadersSchema = StandardSchemaV1<Record<string, string | string[] | undefined>>;
|
|
41
|
+
/** Options shared by a single route and a route in a group. */
|
|
28
42
|
export type HTTPRouteBaseConfig = {
|
|
29
43
|
/** How the body is serialised. Defaults to JSON; `xml` is for routes a caller you do not control insists on. */
|
|
30
44
|
contentType?: 'xml' | 'json';
|
|
@@ -62,12 +76,14 @@ export interface PikkuHTTPAuthInfo {
|
|
|
62
76
|
resource?: URL;
|
|
63
77
|
extra?: Record<string, unknown>;
|
|
64
78
|
}
|
|
79
|
+
/** The HTTP part of a wire: the request and response a function was invoked with, when it was invoked over HTTP. */
|
|
65
80
|
export interface PikkuHTTP<In = unknown> {
|
|
66
81
|
request?: PikkuHTTPRequest<In>;
|
|
67
82
|
response?: PikkuHTTPResponse;
|
|
68
83
|
/** Verified token claims, when the transport was handed them. */
|
|
69
84
|
authInfo?: PikkuHTTPAuthInfo;
|
|
70
85
|
}
|
|
86
|
+
/** A parsed query string. Depending on the adapter's parser a value may be a string, an array, or a nested object. */
|
|
71
87
|
export type PikkuQuery<T = Record<string, string | undefined>> = Record<string, string | T | null | Array<T | null>>;
|
|
72
88
|
/**
|
|
73
89
|
* The keys every HTTP wiring takes, whatever it is wired to. The three that
|
|
@@ -132,6 +148,7 @@ type HTTPWiringMethod<In> = {
|
|
|
132
148
|
query?: Array<keyof In>;
|
|
133
149
|
sse?: undefined;
|
|
134
150
|
};
|
|
151
|
+
/** The configuration {@link wireHTTP} takes. The generated `wireHTTP` in an app narrows the function, permission and middleware types to the app's own. */
|
|
135
152
|
export type CoreHTTPFunctionWiring<In, Out, R extends string, PikkuFunction extends CorePikkuFunction<In, Out, any, any, any> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out, any, any, any> = CorePikkuFunctionSessionless<In, Out>, PikkuPermission extends CorePikkuPermission<In, any, any> = CorePikkuPermission<In, any, any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>> = HTTPWiringShared<R, PikkuMiddleware> & HTTPWiringAuth<In, Out, PikkuFunction, PikkuFunctionSessionless, PikkuPermission, PikkuMiddleware> & HTTPWiringMethod<In>;
|
|
136
153
|
export type HTTPFunctionMetaInputTypes = {
|
|
137
154
|
params?: string;
|
|
@@ -159,7 +176,14 @@ export type HTTPWiringMeta = CommonWireMeta & {
|
|
|
159
176
|
sse?: true;
|
|
160
177
|
groupBasePath?: string;
|
|
161
178
|
};
|
|
179
|
+
/** Generated metadata for every wired route, keyed by method and then route. */
|
|
162
180
|
export type HTTPWiringsMeta = Record<HTTPMethod, Record<string, HTTPWiringMeta>>;
|
|
181
|
+
/**
|
|
182
|
+
* The request interface every runtime adapter implements, so functions and middleware read requests the same way on every host.
|
|
183
|
+
*
|
|
184
|
+
* `data()` merges path params, query and body into the function's input.
|
|
185
|
+
* `params()` is empty until a route has matched.
|
|
186
|
+
*/
|
|
163
187
|
export interface PikkuHTTPRequest<In = unknown> {
|
|
164
188
|
method(): HTTPMethod;
|
|
165
189
|
path(): string;
|
|
@@ -173,6 +197,7 @@ export interface PikkuHTTPRequest<In = unknown> {
|
|
|
173
197
|
setParams(params: Record<string, string | string[] | undefined>): void;
|
|
174
198
|
query(): PikkuQuery;
|
|
175
199
|
}
|
|
200
|
+
/** The response interface every runtime adapter implements. Methods return `this` so calls can be chained; the optional members exist only on adapters that support streaming. */
|
|
176
201
|
export interface PikkuHTTPResponse<Out = unknown> {
|
|
177
202
|
readonly statusCode: number;
|
|
178
203
|
status(code: number): this;
|
|
@@ -205,9 +230,11 @@ export type HTTPRoutesGroupConfig<PikkuPermission extends CorePikkuPermission<an
|
|
|
205
230
|
auth?: boolean;
|
|
206
231
|
middleware?: PikkuMiddleware[];
|
|
207
232
|
};
|
|
233
|
+
/** A map of named routes, route groups and nested maps, as accepted by {@link defineHTTPRoutes} and {@link wireHTTPRoutes}. Keys are labels only and never form part of a path. */
|
|
208
234
|
export type HTTPRouteMap = {
|
|
209
235
|
[key: string]: HTTPRouteConfig | HTTPRouteMap | HTTPRouteContract;
|
|
210
236
|
};
|
|
237
|
+
/** A route group returned by {@link defineHTTPRoutes}: group options plus its routes, with the route map's type preserved. */
|
|
211
238
|
export type HTTPRouteContract<T extends HTTPRouteMap = HTTPRouteMap> = HTTPRoutesGroupConfig & {
|
|
212
239
|
routes: T;
|
|
213
240
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { PikkuFetchHTTPRequest, DEFAULT_MAX_BODY_SIZE, } from './pikku-fetch-http-request.js';
|
|
2
2
|
export { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
3
|
+
export { mergeRequestData } from './merge-request-data.js';
|
|
3
4
|
export { logRoutes } from './log-http-routes.js';
|
|
4
5
|
export { fetch, fetchData, wireHTTP, addHTTPMiddleware } from './http-runner.js';
|
|
5
6
|
export { wireHTTPRoutes, defineHTTPRoutes } from './http-routes.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { PikkuFetchHTTPRequest, DEFAULT_MAX_BODY_SIZE, } from './pikku-fetch-http-request.js';
|
|
2
2
|
export { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
3
|
+
export { mergeRequestData } from './merge-request-data.js';
|
|
3
4
|
export { logRoutes } from './log-http-routes.js';
|
|
4
5
|
export { fetch, fetchData, wireHTTP, addHTTPMiddleware } from './http-runner.js';
|
|
5
6
|
export { wireHTTPRoutes, defineHTTPRoutes } from './http-routes.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges route params, query and body into the single input object a Pikku
|
|
3
|
+
* function receives. Earlier parts win; a key present in more than one part
|
|
4
|
+
* must carry an equivalent value (`'1'` and `1`, `'true'` and `true`), or the
|
|
5
|
+
* request is rejected. Prototype-polluting keys are dropped.
|
|
6
|
+
*
|
|
7
|
+
* Every HTTP runtime calls this from `PikkuHTTPRequest.data()`, so the merge
|
|
8
|
+
* and the conflict rule are identical wherever a function is served.
|
|
9
|
+
*
|
|
10
|
+
* @throws UnprocessableContentError when two parts disagree on a key.
|
|
11
|
+
*/
|
|
12
|
+
export declare const mergeRequestData: <In = unknown>(...parts: Array<Readonly<Record<string, unknown>>>) => In;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { UnprocessableContentError } from '../../errors/errors.js';
|
|
2
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
3
|
+
/**
|
|
4
|
+
* Merges route params, query and body into the single input object a Pikku
|
|
5
|
+
* function receives. Earlier parts win; a key present in more than one part
|
|
6
|
+
* must carry an equivalent value (`'1'` and `1`, `'true'` and `true`), or the
|
|
7
|
+
* request is rejected. Prototype-polluting keys are dropped.
|
|
8
|
+
*
|
|
9
|
+
* Every HTTP runtime calls this from `PikkuHTTPRequest.data()`, so the merge
|
|
10
|
+
* and the conflict rule are identical wherever a function is served.
|
|
11
|
+
*
|
|
12
|
+
* @throws UnprocessableContentError when two parts disagree on a key.
|
|
13
|
+
*/
|
|
14
|
+
export const mergeRequestData = (...parts) => {
|
|
15
|
+
const merged = {};
|
|
16
|
+
for (const part of parts) {
|
|
17
|
+
for (const [key, value] of Object.entries(part)) {
|
|
18
|
+
if (FORBIDDEN_KEYS.has(key)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (!Object.hasOwn(merged, key)) {
|
|
22
|
+
merged[key] = value;
|
|
23
|
+
}
|
|
24
|
+
else if (!valuesAreEquivalent(merged[key], value)) {
|
|
25
|
+
throw new UnprocessableContentError(`Conflicting values for key "${key}": "${String(merged[key])}" vs "${String(value)}"`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return merged;
|
|
30
|
+
};
|
|
31
|
+
const valuesAreEquivalent = (a, b) => coerce(a) === coerce(b);
|
|
32
|
+
const coerce = (value) => {
|
|
33
|
+
if (typeof value === 'string') {
|
|
34
|
+
if (value === 'true')
|
|
35
|
+
return true;
|
|
36
|
+
if (value === 'false')
|
|
37
|
+
return false;
|
|
38
|
+
const num = Number(value);
|
|
39
|
+
return isNaN(num) ? value : num;
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HTTPMethod, PikkuHTTPRequest, PikkuQuery } from './http.types.js';
|
|
2
|
+
/** The request body limit, in bytes (10 MiB), applied when a web `Request` is wrapped and no `maxBodySize` is given. A larger body is refused with a 413 before it is fully read. */
|
|
2
3
|
export declare const DEFAULT_MAX_BODY_SIZE: number;
|
|
3
4
|
export type PikkuFetchHTTPRequestOptions = Partial<{
|
|
4
5
|
/** Maximum request body size in bytes. Defaults to {@link DEFAULT_MAX_BODY_SIZE}. */
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { parse as parseQuery } from 'picoquery';
|
|
2
2
|
import { parseCookie } from 'cookie';
|
|
3
3
|
import { PayloadTooLargeError, UnprocessableContentError, } from '../../errors/errors.js';
|
|
4
|
+
import { mergeRequestData } from './merge-request-data.js';
|
|
5
|
+
/** The request body limit, in bytes (10 MiB), applied when a web `Request` is wrapped and no `maxBodySize` is given. A larger body is refused with a 413 before it is fully read. */
|
|
4
6
|
export const DEFAULT_MAX_BODY_SIZE = 10 * 1024 * 1024;
|
|
5
7
|
/**
|
|
6
8
|
* @group RequestResponse
|
|
@@ -135,22 +137,7 @@ export class PikkuFetchHTTPRequest {
|
|
|
135
137
|
}
|
|
136
138
|
async data() {
|
|
137
139
|
const body = await this.body();
|
|
138
|
-
|
|
139
|
-
const merged = {};
|
|
140
|
-
for (const part of parts) {
|
|
141
|
-
for (const [key, value] of Object.entries(part)) {
|
|
142
|
-
if (key === '__proto__' ||
|
|
143
|
-
key === 'constructor' ||
|
|
144
|
-
key === 'prototype') {
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
if (key in merged && !valuesAreEquivalent(merged[key], value)) {
|
|
148
|
-
throw new UnprocessableContentError(`Conflicting values for key "${key}": "${merged[key]}" vs "${value}"`);
|
|
149
|
-
}
|
|
150
|
-
merged[key] ??= value;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return merged;
|
|
140
|
+
return mergeRequestData(this.params(), this.query(), body);
|
|
154
141
|
}
|
|
155
142
|
async body() {
|
|
156
143
|
const noBodyMethods = ['get', 'head', 'options', 'delete'];
|
|
@@ -202,19 +189,3 @@ export class PikkuFetchHTTPRequest {
|
|
|
202
189
|
return body;
|
|
203
190
|
}
|
|
204
191
|
}
|
|
205
|
-
function valuesAreEquivalent(a, b) {
|
|
206
|
-
return coerce(a) === coerce(b);
|
|
207
|
-
}
|
|
208
|
-
function coerce(value) {
|
|
209
|
-
if (typeof value === 'boolean' || typeof value === 'number')
|
|
210
|
-
return value;
|
|
211
|
-
if (typeof value === 'string') {
|
|
212
|
-
if (value === 'true')
|
|
213
|
-
return true;
|
|
214
|
-
if (value === 'false')
|
|
215
|
-
return false;
|
|
216
|
-
const num = Number(value);
|
|
217
|
-
return isNaN(num) ? value : num;
|
|
218
|
-
}
|
|
219
|
-
return value;
|
|
220
|
-
}
|