@pikku/core 0.12.142 → 0.12.144
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 +11 -1
- package/dist/services/incoming-webhook-service.js +5 -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 +16 -0
- package/dist/services/scheduler-service.js +12 -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/command-parser.d.ts +13 -0
- package/dist/wirings/cli/command-parser.js +12 -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/wirings/queue/in-memory-queue-service.d.ts +23 -0
- package/dist/wirings/queue/in-memory-queue-service.js +129 -0
- package/dist/wirings/queue/index.d.ts +2 -1
- 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 +56 -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/signed-queue-service.d.ts +4 -1
- package/dist/wirings/queue/signed-queue-service.js +3 -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 +2 -1
- 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 +15 -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 -6961
- package/dist/services/in-memory-queue-service.d.ts +0 -8
- package/dist/services/in-memory-queue-service.js +0 -54
- 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-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 -46
- 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 -181
- 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 -34
- 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,13 +1,13 @@
|
|
|
1
1
|
import { beginChanges } from './abort-scope.js';
|
|
2
|
-
import { forwardStepName, isCompensationStepName } from '
|
|
2
|
+
import { forwardStepName, isCompensationStepName, } from '../compensation-name.js';
|
|
3
3
|
import { runMiddleware, combineMiddleware } from '../middleware-runner.js';
|
|
4
|
-
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../
|
|
4
|
+
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../channel-middleware-runner.js';
|
|
5
5
|
import { runPermissions } from '../permissions.js';
|
|
6
6
|
import { withoutSecrets } from '../services/secretless.js';
|
|
7
7
|
import { getCreateWireServices, pikkuState } from '../pikku-state.js';
|
|
8
8
|
import { applyDefaultsFromSchema, coerceTopLevelDataFromSchema, validateSchema, } from '../schema.js';
|
|
9
9
|
import { parseVersionedId } from '../version.js';
|
|
10
|
-
import { PikkuSessionService } from '../services/user-session-service.js';
|
|
10
|
+
import { PikkuSessionService, createFunctionSessionWireProps, } from '../services/user-session-service.js';
|
|
11
11
|
import { MissingSessionError, ReadonlySessionError } from '../errors/errors.js';
|
|
12
12
|
import { verifyScopes } from '../scopes.js';
|
|
13
13
|
import { assertFeatureAvailable } from '../wirings/flag/assert-feature-available.js';
|
|
@@ -22,6 +22,13 @@ import { getOrCreatePackageSingletonServices } from '../wirings/addon/addon-runn
|
|
|
22
22
|
import { resolveAddonAuth, resolveAddonFunctionTarget, resolveAddonScopes, resolveAddonTagMiddleware, } from '../wirings/addon/wire-addon.js';
|
|
23
23
|
import { closeWireServices } from '../utils.js';
|
|
24
24
|
async function resolveSession(wire, singletonServices, sessionService) {
|
|
25
|
+
// A session middleware established lives on the session service, not on the
|
|
26
|
+
// transport's snapshot of the wire. Read it from there, so it is what the
|
|
27
|
+
// function sees and what its user id is resolved from.
|
|
28
|
+
// knowledge: decisions/security/set-session-persists-and-set-initial-session-does-not.md
|
|
29
|
+
if (!wire.session && sessionService?.get()) {
|
|
30
|
+
wire.session = sessionService.get();
|
|
31
|
+
}
|
|
25
32
|
const pikkuUserId = defaultPikkuUserIdResolver(wire);
|
|
26
33
|
if (pikkuUserId) {
|
|
27
34
|
wire.pikkuUserId = pikkuUserId;
|
|
@@ -45,6 +52,15 @@ async function resolveSession(wire, singletonServices, sessionService) {
|
|
|
45
52
|
sessionService?.setInitial(wire.session);
|
|
46
53
|
}
|
|
47
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Registers a function's config under its id so wirings can run it by name.
|
|
57
|
+
* Generated code calls this for every function codegen found; an app rarely
|
|
58
|
+
* needs to. Registering the same id again replaces the earlier config.
|
|
59
|
+
*
|
|
60
|
+
* @param funcName - The function id, as it appears in the generated metadata.
|
|
61
|
+
* @param funcConfig - The object a `pikkuFunc` / `pikkuSessionlessFunc` returned.
|
|
62
|
+
* @param packageName - The addon package it belongs to; `null` for the app.
|
|
63
|
+
*/
|
|
48
64
|
export const addFunction = (funcName, funcConfig, packageName = null) => {
|
|
49
65
|
pikkuState(packageName, 'function', 'functions').set(funcName, funcConfig);
|
|
50
66
|
};
|
|
@@ -52,6 +68,10 @@ export const getFunctionNames = (packageName = null) => {
|
|
|
52
68
|
const functionsMeta = pikkuState(packageName, 'function', 'meta');
|
|
53
69
|
return Object.keys(functionsMeta);
|
|
54
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Every function id with generated metadata: the app's own, then each addon's
|
|
73
|
+
* prefixed with the namespace it was wired under (`ns:name`).
|
|
74
|
+
*/
|
|
55
75
|
export const getAllFunctionNames = () => {
|
|
56
76
|
const functions = [];
|
|
57
77
|
const mainFunctionsMeta = pikkuState(null, 'function', 'meta');
|
|
@@ -65,6 +85,34 @@ export const getAllFunctionNames = () => {
|
|
|
65
85
|
}
|
|
66
86
|
return functions;
|
|
67
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Runs one registered function the way every wiring does. Each transport's
|
|
90
|
+
* runner (HTTP, channel, queue, scheduler, RPC, MCP, CLI, workflow, agent)
|
|
91
|
+
* ends up here; an app calls it directly only when it is building its own
|
|
92
|
+
* transport.
|
|
93
|
+
*
|
|
94
|
+
* In order, it: resolves the function (falling back from `name@vN` to the
|
|
95
|
+
* unversioned name, and into an addon for `ns:name`), runs the combined
|
|
96
|
+
* middleware, resolves the session, enforces auth, `readonly`, scopes and the
|
|
97
|
+
* feature flag, reads `data()`, applies schema defaults and validation, runs
|
|
98
|
+
* global and function permissions, builds and finally closes the wire
|
|
99
|
+
* services, and calls the function. The function and its permissions receive
|
|
100
|
+
* services whose `secrets` throws on access — they read secrets through the
|
|
101
|
+
* declared typed wrappers instead.
|
|
102
|
+
*
|
|
103
|
+
* @param wireType - The transport, recorded on `wire.wireType` if unset.
|
|
104
|
+
* @param wireId - The wiring's id (route, queue name, …), recorded on
|
|
105
|
+
* `wire.wireId` if unset. Middleware registered against it is applied.
|
|
106
|
+
* @param funcName - The registered function id.
|
|
107
|
+
* @returns Whatever the function returns.
|
|
108
|
+
* @throws {MissingSessionError} A session is required and none resolved.
|
|
109
|
+
* @throws {ReadonlySessionError} A readonly session called a mutating function.
|
|
110
|
+
* @throws {MissingScopeError} The session lacks a required scope.
|
|
111
|
+
* @throws {FeatureUnavailableError} The function's feature flag is off.
|
|
112
|
+
* @throws {ForbiddenError} A permission refused the call.
|
|
113
|
+
* @throws {Error} The function or its metadata is not registered. Errors thrown
|
|
114
|
+
* by validation, middleware and the function itself propagate unchanged.
|
|
115
|
+
*/
|
|
68
116
|
export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, wireServices: providedWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedChannelMiddleware, wireChannelMiddleware, coerceDataFromSchema, wire, sessionService, credentialWireService, packageName = null, addonInstance, }) => {
|
|
69
117
|
wire.wireType ??= wireType;
|
|
70
118
|
wire.wireId ??= wireId;
|
|
@@ -204,17 +252,13 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
204
252
|
const executeFunction = async () => {
|
|
205
253
|
await resolveSession(invocationWire, resolvedSingletonServices, sessionService);
|
|
206
254
|
if (sessionService) {
|
|
207
|
-
invocationWire
|
|
208
|
-
invocationWire.setSession = (s) => sessionService.set(s);
|
|
209
|
-
invocationWire.clearSession = () => sessionService.clear();
|
|
210
|
-
invocationWire.getSession = () => sessionService.get();
|
|
211
|
-
invocationWire.hasSessionChanged = () => sessionService.sessionChanged;
|
|
255
|
+
Object.assign(invocationWire, createFunctionSessionWireProps(sessionService));
|
|
212
256
|
}
|
|
213
257
|
const session = invocationWire.session;
|
|
214
258
|
if (funcMeta.sessionless) {
|
|
215
259
|
if (wiringAuth === true ||
|
|
216
260
|
funcConfig.auth === true ||
|
|
217
|
-
resolveAddonAuth(
|
|
261
|
+
resolveAddonAuth(funcPackageName, addonInstance?.namespace)) {
|
|
218
262
|
if (!session) {
|
|
219
263
|
throw new MissingSessionError('Authentication required');
|
|
220
264
|
}
|
|
@@ -239,7 +283,9 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
239
283
|
invocationWire.beginChanges = () => beginChanges(abortScope);
|
|
240
284
|
}
|
|
241
285
|
// knowledge: decisions/security/addon-scopes-are-resolved-where-the-function-runs.md
|
|
242
|
-
|
|
286
|
+
// The function's package, not the wire's: a `ref('ns:fn')` route stays the
|
|
287
|
+
// app's, and reading the wire's left it outside the addon's floor.
|
|
288
|
+
const addonScopes = resolveAddonScopes(funcPackageName, addonInstance?.namespace);
|
|
243
289
|
const functionScopes = funcConfig.scopes ?? funcMeta.scopes;
|
|
244
290
|
verifyScopes(addonScopes.length > 0
|
|
245
291
|
? [...addonScopes, ...(functionScopes ?? [])]
|
|
@@ -330,7 +376,7 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
330
376
|
}
|
|
331
377
|
}
|
|
332
378
|
};
|
|
333
|
-
const addonTagMiddleware = resolveAddonTagMiddleware(
|
|
379
|
+
const addonTagMiddleware = resolveAddonTagMiddleware(funcPackageName, addonInstance?.namespace);
|
|
334
380
|
const allMiddleware = combineMiddleware(wireType, wireId, {
|
|
335
381
|
wireInheritedMiddleware: inheritedMiddleware,
|
|
336
382
|
wireMiddleware: addonTagMiddleware.length > 0
|
|
@@ -7,15 +7,50 @@ import type { PikkuError } from '../errors/error-handler.js';
|
|
|
7
7
|
import type { CoreNodeConfig } from '../wirings/node/node.types.js';
|
|
8
8
|
import type { ScenarioSurface } from '../wirings/workflow/scenario-step.types.js';
|
|
9
9
|
import type { Safe } from '../classification/secret-value.js';
|
|
10
|
+
/**
|
|
11
|
+
* The body of a function that requires a session: `(services, data, wire)`,
|
|
12
|
+
* with `wire.session` typed as present. `pikkuFunc` takes one of these; the
|
|
13
|
+
* runner refuses the call with `MissingSessionError` before the body runs when
|
|
14
|
+
* there is no session.
|
|
15
|
+
*/
|
|
10
16
|
export type CorePikkuFunction<In, Out, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out, true, Session, PikkuRPC, null, string> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Safe<Out>> : Promise<Safe<Out>> | Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* The body of a function that may run without a session, so `wire.session` is
|
|
19
|
+
* optional. `pikkuSessionlessFunc` takes one of these.
|
|
20
|
+
*/
|
|
11
21
|
export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out, false, Session, PikkuRPC, null, string> = PikkuWire<In, Out, false, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Safe<Out>> : Promise<Safe<Out>> | Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* A permission check: resolves `true` to allow the call. Runs after input
|
|
24
|
+
* validation, so `data` is the validated input. Its services have no
|
|
25
|
+
* `secrets`.
|
|
26
|
+
*/
|
|
12
27
|
export type CorePikkuPermission<In = any, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Wire extends PikkuWire<In, never, false, any, PikkuRPC, never, never> = PikkuWire<In, never, false, any, PikkuRPC, never, never>> = (services: Services, data: In, wire: Wire) => Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* The object form of {@link pikkuPermission}, for a check that carries a name
|
|
30
|
+
* or description.
|
|
31
|
+
*/
|
|
13
32
|
export type CorePikkuPermissionConfig<In = any, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Wire extends PikkuWire<In, never, false, any, PikkuRPC, never, never> = PikkuWire<In, never, false, any, PikkuRPC, never, never>> = {
|
|
14
33
|
func: CorePikkuPermission<In, Services, Wire>;
|
|
15
34
|
name?: string;
|
|
16
35
|
description?: string;
|
|
17
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Declares a permission: an async check that resolves `true` to allow a call
|
|
39
|
+
* and `false` to refuse it with `ForbiddenError` (403). It receives the
|
|
40
|
+
* services (without `secrets`), the validated input and the wire.
|
|
41
|
+
*
|
|
42
|
+
* Attach it through a function's or wiring's `permissions`: within one group
|
|
43
|
+
* the keys are alternatives, so the call passes when any key passes, and an
|
|
44
|
+
* array under a key must pass in full. Global permissions from
|
|
45
|
+
* `addGlobalPermission` must all pass as well.
|
|
46
|
+
*
|
|
47
|
+
* @example snippet: permissionFunction
|
|
48
|
+
*/
|
|
18
49
|
export declare const pikkuPermission: <In = any, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Wire extends PickRequired<PikkuWire<In, never, false, any, PikkuRPC, never, never>, 'session'> = PickRequired<PikkuWire<In, never, false, any, PikkuRPC, never, never>, 'session'>>(permission: CorePikkuPermission<In, Services, Wire> | CorePikkuPermissionConfig<In, Services, Wire>) => CorePikkuPermission<In, Services, Wire>;
|
|
50
|
+
/**
|
|
51
|
+
* A function that takes options and returns a permission, as declared with
|
|
52
|
+
* {@link pikkuPermissionFactory}.
|
|
53
|
+
*/
|
|
19
54
|
export type CorePikkuPermissionFactory<In = any, Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Wire extends PikkuWire<In, never, false, any, PikkuRPC, never, never> = PikkuWire<In, never, false, any, PikkuRPC, never, never>> = (input: In) => CorePikkuPermission<any, Services, Wire>;
|
|
20
55
|
/**
|
|
21
56
|
* Declares a permission that takes configuration, so one check serves many
|
|
@@ -35,7 +70,12 @@ export type CorePikkuApprovalDescription<In = any, Services extends CoreSecretle
|
|
|
35
70
|
* @example snippet: approvalDescription
|
|
36
71
|
*/
|
|
37
72
|
export declare const pikkuApprovalDescription: <In = any, Services extends CoreSecretlessSingletonServices = CoreSecretlessSingletonServices>(fn: CorePikkuApprovalDescription<In, Services>) => CorePikkuApprovalDescription<In, Services>;
|
|
73
|
+
/** A session check: receives the services and the session, never the input. */
|
|
38
74
|
export type CorePikkuAuth<Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Session extends CoreUserSession = CoreUserSession> = (services: Services, session: Session) => Promise<boolean> | boolean;
|
|
75
|
+
/**
|
|
76
|
+
* The object form of {@link pikkuAuth}, for a check that carries a name or
|
|
77
|
+
* description.
|
|
78
|
+
*/
|
|
39
79
|
export type CorePikkuAuthConfig<Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Session extends CoreUserSession = CoreUserSession> = {
|
|
40
80
|
func: CorePikkuAuth<Services, Session>;
|
|
41
81
|
name?: string;
|
|
@@ -50,7 +90,22 @@ export type CorePikkuAuthConfig<Services extends CoreSecretlessSingletonServices
|
|
|
50
90
|
export type AuthBranded = {
|
|
51
91
|
__pikkuAuth?: true;
|
|
52
92
|
};
|
|
93
|
+
/**
|
|
94
|
+
* Declares a permission that depends only on the session, not the input. The
|
|
95
|
+
* resulting permission refuses outright when there is no session, so the
|
|
96
|
+
* check itself always sees one.
|
|
97
|
+
*
|
|
98
|
+
* Because it does not read the input, an agent can evaluate it ahead of time
|
|
99
|
+
* to decide which tools a session may be offered (see `checkAuthPermissions`);
|
|
100
|
+
* ordinary permissions are only checked when a tool is actually called.
|
|
101
|
+
*
|
|
102
|
+
* @example snippet: shopIsAuthenticated
|
|
103
|
+
*/
|
|
53
104
|
export declare const pikkuAuth: <Services extends CoreSecretlessSingletonServices = SecretlessServices<CoreServices>, Session extends CoreUserSession = CoreUserSession>(auth: CorePikkuAuth<Services, Session> | CorePikkuAuthConfig<Services, Session>) => CorePikkuPermission<any, Services, any>;
|
|
105
|
+
/**
|
|
106
|
+
* Permissions keyed by name. The call passes when any key passes (OR); an array
|
|
107
|
+
* under one key must pass in full (AND).
|
|
108
|
+
*/
|
|
54
109
|
export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
|
|
55
110
|
/**
|
|
56
111
|
* A lifecycle hook: same call signature as the function it hangs off, return
|
|
@@ -58,6 +113,10 @@ export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Re
|
|
|
58
113
|
* it is never recorded and never replayed.
|
|
59
114
|
*/
|
|
60
115
|
export type CorePikkuFunctionHook<Services = any, Data = any, Wire = any> = (services: Services, data: Data, wire: Wire) => Promise<void> | void;
|
|
116
|
+
/**
|
|
117
|
+
* Everything a function is declared with: its body and the options
|
|
118
|
+
* `pikkuFunc` / `pikkuSessionlessFunc` accept.
|
|
119
|
+
*/
|
|
61
120
|
export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, InputSchema extends StandardSchemaV1 | undefined = undefined, OutputSchema extends StandardSchemaV1 | undefined = undefined, Scope extends string = string, FeatureFlagName extends string = string> = {
|
|
62
121
|
/** A human name for this function, shown wherever it is listed rather than called. */
|
|
63
122
|
title?: string;
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares a permission: an async check that resolves `true` to allow a call
|
|
3
|
+
* and `false` to refuse it with `ForbiddenError` (403). It receives the
|
|
4
|
+
* services (without `secrets`), the validated input and the wire.
|
|
5
|
+
*
|
|
6
|
+
* Attach it through a function's or wiring's `permissions`: within one group
|
|
7
|
+
* the keys are alternatives, so the call passes when any key passes, and an
|
|
8
|
+
* array under a key must pass in full. Global permissions from
|
|
9
|
+
* `addGlobalPermission` must all pass as well.
|
|
10
|
+
*
|
|
11
|
+
* @example snippet: permissionFunction
|
|
12
|
+
*/
|
|
1
13
|
export const pikkuPermission = (permission) => {
|
|
2
14
|
return typeof permission === 'function' ? permission : permission.func;
|
|
3
15
|
};
|
|
@@ -18,6 +30,17 @@ export const pikkuPermissionFactory = (factory) => {
|
|
|
18
30
|
export const pikkuApprovalDescription = (fn) => {
|
|
19
31
|
return fn;
|
|
20
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Declares a permission that depends only on the session, not the input. The
|
|
35
|
+
* resulting permission refuses outright when there is no session, so the
|
|
36
|
+
* check itself always sees one.
|
|
37
|
+
*
|
|
38
|
+
* Because it does not read the input, an agent can evaluate it ahead of time
|
|
39
|
+
* to decide which tools a session may be offered (see `checkAuthPermissions`);
|
|
40
|
+
* ordinary permissions are only checked when a tool is actually called.
|
|
41
|
+
*
|
|
42
|
+
* @example snippet: shopIsAuthenticated
|
|
43
|
+
*/
|
|
21
44
|
export const pikkuAuth = (auth) => {
|
|
22
45
|
const fn = typeof auth === 'function' ? auth : auth.func;
|
|
23
46
|
const wrapper = async (services, _data, wire) => {
|
|
@@ -18,6 +18,10 @@ export interface ListInput<F extends Record<string, unknown> = Record<string, ne
|
|
|
18
18
|
/** Unstructured text search across server-configured fields. */
|
|
19
19
|
search?: string;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The output a list function returns: one page of rows and the cursor for the
|
|
23
|
+
* next.
|
|
24
|
+
*/
|
|
21
25
|
export interface ListOutput<Row> {
|
|
22
26
|
rows: Row[];
|
|
23
27
|
/** Null when no more pages. */
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { CoreSingletonServices, ServerLifecycle } from './types/core.types.js';
|
|
2
2
|
/** Stops addon package services first, then the parent singleton services. */
|
|
3
3
|
export declare const stopSingletonServices: () => Promise<void>;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Wrap server lifecycle hooks so the inspector can discover them.
|
|
6
|
+
*
|
|
7
|
+
* @example snippet: serverLifecycle
|
|
8
|
+
*/
|
|
5
9
|
export declare const pikkuServerLifecycle: <SS extends CoreSingletonServices = CoreSingletonServices>(lifecycle: ServerLifecycle<SS>) => ServerLifecycle<SS>;
|
|
10
|
+
/**
|
|
11
|
+
* Calls `run` once when the process receives one of `signals` (default
|
|
12
|
+
* `SIGINT` and `SIGTERM`); later signals are ignored while it runs. Does
|
|
13
|
+
* nothing outside Node-like runtimes. It does not exit the process.
|
|
14
|
+
*
|
|
15
|
+
* @returns A function that removes the handlers.
|
|
16
|
+
*/
|
|
6
17
|
export declare const onShutdownSignals: (run: (signal: NodeJS.Signals) => void | Promise<void>, signals?: NodeJS.Signals[]) => (() => void);
|
package/dist/lifecycle.js
CHANGED
|
@@ -34,8 +34,19 @@ export const stopSingletonServices = async () => {
|
|
|
34
34
|
await stopService(logger, name, service);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Wrap server lifecycle hooks so the inspector can discover them.
|
|
39
|
+
*
|
|
40
|
+
* @example snippet: serverLifecycle
|
|
41
|
+
*/
|
|
38
42
|
export const pikkuServerLifecycle = (lifecycle) => lifecycle;
|
|
43
|
+
/**
|
|
44
|
+
* Calls `run` once when the process receives one of `signals` (default
|
|
45
|
+
* `SIGINT` and `SIGTERM`); later signals are ignored while it runs. Does
|
|
46
|
+
* nothing outside Node-like runtimes. It does not exit the process.
|
|
47
|
+
*
|
|
48
|
+
* @returns A function that removes the handlers.
|
|
49
|
+
*/
|
|
39
50
|
export const onShutdownSignals = (run, signals = ['SIGINT', 'SIGTERM']) => {
|
|
40
51
|
const proc = typeof process !== 'undefined' ? process : undefined;
|
|
41
52
|
if (!proc?.on)
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { ForbiddenError } from '../errors/errors.js';
|
|
2
2
|
import { intersectScopes } from '../scopes.js';
|
|
3
3
|
import { pikkuMiddleware, pikkuMiddlewareFactory, } from './middleware-factories.js';
|
|
4
|
+
/**
|
|
5
|
+
* The request header naming the addon a call is made on behalf of, read by
|
|
6
|
+
* {@link addonScopeCap}.
|
|
7
|
+
*/
|
|
4
8
|
export const ADDON_HEADER = 'x-pikku-addon';
|
|
5
9
|
/**
|
|
6
10
|
* Narrows the session to what an addon is allowed to do. A call that names an
|
|
@@ -16,17 +20,17 @@ export const ADDON_HEADER = 'x-pikku-addon';
|
|
|
16
20
|
* Register it after the session middleware: it narrows a session that is
|
|
17
21
|
* already resolved, and a call with no session has nothing to narrow.
|
|
18
22
|
*/
|
|
19
|
-
export const addonScopeCap = pikkuMiddlewareFactory(({ resolve }) => pikkuMiddleware(async (_services, { http,
|
|
23
|
+
export const addonScopeCap = pikkuMiddlewareFactory(({ resolve }) => pikkuMiddleware(async (_services, { http, setInitialSession, getSession }, next) => {
|
|
20
24
|
const name = http?.request?.header(ADDON_HEADER);
|
|
21
25
|
const session = await getSession?.();
|
|
22
|
-
if (!name || !
|
|
26
|
+
if (!name || !setInitialSession || !session) {
|
|
23
27
|
return next();
|
|
24
28
|
}
|
|
25
29
|
const role = await resolve(name);
|
|
26
30
|
if (!role) {
|
|
27
31
|
throw new ForbiddenError(`Unknown addon '${name}'`);
|
|
28
32
|
}
|
|
29
|
-
|
|
33
|
+
setInitialSession({
|
|
30
34
|
...session,
|
|
31
35
|
scopes: intersectScopes(session.scopes, role),
|
|
32
36
|
});
|
|
@@ -5,8 +5,8 @@ import { pikkuMiddleware, pikkuMiddlewareFactory, } from './middleware-factories
|
|
|
5
5
|
*
|
|
6
6
|
* @example snippet: machineAuth
|
|
7
7
|
*/
|
|
8
|
-
export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware(async ({ jwt: jwtService }, { http,
|
|
9
|
-
if (!http?.request || !
|
|
8
|
+
export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware(async ({ jwt: jwtService }, { http, setInitialSession, session }, next) => {
|
|
9
|
+
if (!http?.request || !setInitialSession || session) {
|
|
10
10
|
return next();
|
|
11
11
|
}
|
|
12
12
|
let apiKey = null;
|
|
@@ -19,7 +19,7 @@ export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware
|
|
|
19
19
|
if (apiKey && jwtService) {
|
|
20
20
|
const userSession = await jwtService.decode(apiKey);
|
|
21
21
|
if (userSession) {
|
|
22
|
-
|
|
22
|
+
setInitialSession?.(userSession);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
return next();
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { InvalidSessionError } from '../errors/errors.js';
|
|
2
2
|
import { pikkuMiddleware, pikkuMiddlewareFactory, } from './middleware-factories.js';
|
|
3
|
-
|
|
4
|
-
if (a.length !== b.length)
|
|
5
|
-
return false;
|
|
6
|
-
let result = 0;
|
|
7
|
-
for (let i = 0; i < a.length; i++) {
|
|
8
|
-
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
9
|
-
}
|
|
10
|
-
return result === 0;
|
|
11
|
-
};
|
|
3
|
+
import { timingSafeStringEqual } from '../utils/hmac.js';
|
|
12
4
|
/**
|
|
13
5
|
* Validates a bearer token: JWT-decoded by default, or compared in constant
|
|
14
6
|
* time against a static `value` or a `secretId` resolved through the secrets
|
|
@@ -16,8 +8,8 @@ const constantTimeEqual = (a, b) => {
|
|
|
16
8
|
*
|
|
17
9
|
* @example snippet: machineAuth
|
|
18
10
|
*/
|
|
19
|
-
export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddleware(async ({ jwt: jwtService, secrets }, { http,
|
|
20
|
-
if (!http?.request || !
|
|
11
|
+
export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddleware(async ({ jwt: jwtService, secrets }, { http, setInitialSession, session }, next) => {
|
|
12
|
+
if (!http?.request || !setInitialSession || session) {
|
|
21
13
|
return next();
|
|
22
14
|
}
|
|
23
15
|
const authHeader = http.request.header('authorization') ||
|
|
@@ -40,7 +32,7 @@ export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddle
|
|
|
40
32
|
.catch(() => undefined);
|
|
41
33
|
expected = stored?.reveal();
|
|
42
34
|
}
|
|
43
|
-
if (expected &&
|
|
35
|
+
if (expected && timingSafeStringEqual(bearerToken, expected)) {
|
|
44
36
|
userSession = token.userSession;
|
|
45
37
|
}
|
|
46
38
|
}
|
|
@@ -48,7 +40,7 @@ export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddle
|
|
|
48
40
|
userSession = await jwtService.decode(bearerToken);
|
|
49
41
|
}
|
|
50
42
|
if (userSession) {
|
|
51
|
-
|
|
43
|
+
setInitialSession?.(userSession);
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
46
|
return next();
|
|
@@ -34,8 +34,8 @@ export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn })
|
|
|
34
34
|
path: '/',
|
|
35
35
|
...options,
|
|
36
36
|
};
|
|
37
|
-
return pikkuMiddleware(async ({ jwt: jwtService, logger }, { http,
|
|
38
|
-
if (!http?.request || !
|
|
37
|
+
return pikkuMiddleware(async ({ jwt: jwtService, logger }, { http, setInitialSession, getSession, session, hasSessionChanged }, next) => {
|
|
38
|
+
if (!http?.request || !setInitialSession || session) {
|
|
39
39
|
return next();
|
|
40
40
|
}
|
|
41
41
|
const cookieValue = http.request.cookie(name);
|
|
@@ -47,7 +47,7 @@ export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn })
|
|
|
47
47
|
// standard JWT timestamp, so an identity-less token is treated as no
|
|
48
48
|
// session rather than as an authenticated one.
|
|
49
49
|
if (userSession && hasSessionIdentity(userSession)) {
|
|
50
|
-
|
|
50
|
+
setInitialSession?.(userSession);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
await next();
|
|
@@ -2,7 +2,24 @@ import type { CoreSingletonServices, CoreUserSession } from '../types/core.types
|
|
|
2
2
|
import type { CorePikkuChannelMiddleware, CorePikkuChannelMiddlewareFactory } from '../wirings/channel/channel.types.js';
|
|
3
3
|
import type { PikkuAgentMiddlewareHooks } from '../wirings/agent/agent.types.js';
|
|
4
4
|
import type { CorePikkuMiddleware, CorePikkuMiddlewareConfig, CorePikkuMiddlewareFactory } from './middleware.types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Declares middleware that runs around a function: authentication, logging,
|
|
7
|
+
* headers, rate limits. Takes the middleware itself, or `{ func, name,
|
|
8
|
+
* description, priority }`; `priority` (default `medium`) orders it among the
|
|
9
|
+
* other middleware on the same invocation, `highest` outermost.
|
|
10
|
+
*
|
|
11
|
+
* The inspector reads the destructured services and wire parameters to know
|
|
12
|
+
* what the middleware uses, so destructure them rather than taking them whole.
|
|
13
|
+
*
|
|
14
|
+
* @example snippet: corsMiddleware
|
|
15
|
+
*/
|
|
5
16
|
export declare const pikkuMiddleware: <SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession>(middleware: CorePikkuMiddleware<SingletonServices, UserSession> | CorePikkuMiddlewareConfig<SingletonServices, UserSession>) => CorePikkuMiddleware<SingletonServices, UserSession>;
|
|
17
|
+
/**
|
|
18
|
+
* Declares middleware that takes options, so one definition can be wired
|
|
19
|
+
* several times with different configuration.
|
|
20
|
+
*
|
|
21
|
+
* @example snippet: middlewareFactory
|
|
22
|
+
*/
|
|
6
23
|
export declare const pikkuMiddlewareFactory: <In = any>(factory: CorePikkuMiddlewareFactory<In>) => CorePikkuMiddlewareFactory<In>;
|
|
7
24
|
/**
|
|
8
25
|
* Declares middleware for a channel — it runs around the connection and its
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares middleware that runs around a function: authentication, logging,
|
|
3
|
+
* headers, rate limits. Takes the middleware itself, or `{ func, name,
|
|
4
|
+
* description, priority }`; `priority` (default `medium`) orders it among the
|
|
5
|
+
* other middleware on the same invocation, `highest` outermost.
|
|
6
|
+
*
|
|
7
|
+
* The inspector reads the destructured services and wire parameters to know
|
|
8
|
+
* what the middleware uses, so destructure them rather than taking them whole.
|
|
9
|
+
*
|
|
10
|
+
* @example snippet: corsMiddleware
|
|
11
|
+
*/
|
|
1
12
|
export const pikkuMiddleware = (middleware) => {
|
|
2
13
|
if (typeof middleware === 'function')
|
|
3
14
|
return middleware;
|
|
@@ -7,6 +18,12 @@ export const pikkuMiddleware = (middleware) => {
|
|
|
7
18
|
}
|
|
8
19
|
return func;
|
|
9
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Declares middleware that takes options, so one definition can be wired
|
|
23
|
+
* several times with different configuration.
|
|
24
|
+
*
|
|
25
|
+
* @example snippet: middlewareFactory
|
|
26
|
+
*/
|
|
10
27
|
export const pikkuMiddlewareFactory = (factory) => {
|
|
11
28
|
return factory;
|
|
12
29
|
};
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { CoreSingletonServices, CoreUserSession, PikkuWire } from '../types/core.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Middleware around a function invocation: it receives the services and the
|
|
4
|
+
* wire, and runs the rest of the chain by awaiting `next()`. Not calling `next`
|
|
5
|
+
* stops the chain, so the function never runs; throwing answers with that
|
|
6
|
+
* error.
|
|
7
|
+
*/
|
|
2
8
|
export type CorePikkuMiddleware<SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession> = (services: SingletonServices, wires: PikkuWire, next: () => Promise<void>) => Promise<void>;
|
|
3
9
|
/**
|
|
4
10
|
* Execution order: `highest` runs first (outermost in the onion), `lowest`
|
|
5
11
|
* runs last, closest to the function.
|
|
6
12
|
*/
|
|
7
13
|
export type MiddlewarePriority = 'highest' | 'high' | 'medium' | 'low' | 'lowest';
|
|
14
|
+
/**
|
|
15
|
+
* The object form of {@link pikkuMiddleware}, for middleware that carries a
|
|
16
|
+
* name, description or priority.
|
|
17
|
+
*/
|
|
8
18
|
export type CorePikkuMiddlewareConfig<SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession> = {
|
|
9
19
|
func: CorePikkuMiddleware<SingletonServices, UserSession>;
|
|
10
20
|
name?: string;
|
|
@@ -12,8 +22,21 @@ export type CorePikkuMiddlewareConfig<SingletonServices extends CoreSingletonSer
|
|
|
12
22
|
/** Execution priority. Lower runs first (outermost). Defaults to 'medium'. */
|
|
13
23
|
priority?: MiddlewarePriority;
|
|
14
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* A function that takes options and returns middleware, as declared with
|
|
27
|
+
* {@link pikkuMiddlewareFactory}.
|
|
28
|
+
*/
|
|
15
29
|
export type CorePikkuMiddlewareFactory<In = any, SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession> = (input: In) => CorePikkuMiddleware<SingletonServices, UserSession>;
|
|
30
|
+
/**
|
|
31
|
+
* A list of middleware, or middleware factories, registered together against
|
|
32
|
+
* a tag or route.
|
|
33
|
+
*/
|
|
16
34
|
export type CorePikkuMiddlewareGroup<SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession> = Array<CorePikkuMiddleware<SingletonServices, UserSession> | CorePikkuMiddlewareFactory<any, SingletonServices, UserSession>>;
|
|
35
|
+
/**
|
|
36
|
+
* How codegen records where a piece of inherited middleware comes from: an
|
|
37
|
+
* HTTP route pattern, a tag, or a named wire-level middleware.
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
17
40
|
export type MiddlewareMetadata = {
|
|
18
41
|
type: 'http';
|
|
19
42
|
route: string;
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authenticates calls between deployments of the same app, on the generated
|
|
3
|
+
* remote-RPC route. Once `PIKKU_REMOTE_SECRET` is set it requires a
|
|
4
|
+
* `Bearer` JWT with audience `pikku-remote`; a token bound to a function (`fn`)
|
|
5
|
+
* is only accepted on that function's `/remote/rpc/<fn>` path, and any session
|
|
6
|
+
* it carries is decrypted with the secret and set on the wire.
|
|
7
|
+
*
|
|
8
|
+
* Without the secret it lets non-remote paths through and refuses
|
|
9
|
+
* `/remote/rpc/*`, so the remote surface fails closed.
|
|
10
|
+
*
|
|
11
|
+
* @throws {UnauthorizedError} On a missing, malformed, mis-addressed or
|
|
12
|
+
* undecryptable token.
|
|
13
|
+
* @throws {WeakKeyMaterialError} When the secret is too short to use.
|
|
14
|
+
* @throws {Error} When the secret is set but no JWT service is configured.
|
|
15
|
+
*/
|
|
1
16
|
export declare const pikkuRemoteAuthMiddleware: import("./middleware.types.js").CorePikkuMiddleware<import("../types/core.types.js").CoreSingletonServices<{
|
|
2
17
|
logLevel?: import("../services/logger.js").LogLevel;
|
|
3
18
|
secrets?: {
|
|
@@ -10,7 +10,22 @@ const REMOTE_RPC_PREFIX = '/remote/rpc/';
|
|
|
10
10
|
* past the trust gate and the token's `fn` binding while still being dispatched.
|
|
11
11
|
*/
|
|
12
12
|
const isRemoteRpcPath = (path) => path.toLowerCase().startsWith(REMOTE_RPC_PREFIX);
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Authenticates calls between deployments of the same app, on the generated
|
|
15
|
+
* remote-RPC route. Once `PIKKU_REMOTE_SECRET` is set it requires a
|
|
16
|
+
* `Bearer` JWT with audience `pikku-remote`; a token bound to a function (`fn`)
|
|
17
|
+
* is only accepted on that function's `/remote/rpc/<fn>` path, and any session
|
|
18
|
+
* it carries is decrypted with the secret and set on the wire.
|
|
19
|
+
*
|
|
20
|
+
* Without the secret it lets non-remote paths through and refuses
|
|
21
|
+
* `/remote/rpc/*`, so the remote surface fails closed.
|
|
22
|
+
*
|
|
23
|
+
* @throws {UnauthorizedError} On a missing, malformed, mis-addressed or
|
|
24
|
+
* undecryptable token.
|
|
25
|
+
* @throws {WeakKeyMaterialError} When the secret is too short to use.
|
|
26
|
+
* @throws {Error} When the secret is set but no JWT service is configured.
|
|
27
|
+
*/
|
|
28
|
+
export const pikkuRemoteAuthMiddleware = pikkuMiddleware(async ({ secrets, jwt }, { http, setInitialSession }, next) => {
|
|
14
29
|
if (!http?.request || !secrets) {
|
|
15
30
|
return next();
|
|
16
31
|
}
|
|
@@ -58,8 +73,8 @@ export const pikkuRemoteAuthMiddleware = pikkuMiddleware(async ({ secrets, jwt }
|
|
|
58
73
|
if (payload?.session) {
|
|
59
74
|
try {
|
|
60
75
|
const decrypted = await decryptWithKeyMaterial('PIKKU_REMOTE_SECRET', secret, REMOTE_SESSION_INFO, payload.session);
|
|
61
|
-
if (decrypted?.session &&
|
|
62
|
-
|
|
76
|
+
if (decrypted?.session && setInitialSession) {
|
|
77
|
+
setInitialSession(decrypted.session);
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
catch {
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { UnauthorizedError } from '../errors/errors.js';
|
|
2
2
|
import { REMOTE_JOBS_SECRET_HEADER, REMOTE_JOBS_SECRET_VARIABLE, } from '../services/remote-jobs.js';
|
|
3
3
|
import { pikkuMiddleware } from './middleware-factories.js';
|
|
4
|
-
|
|
5
|
-
if (a.length !== b.length)
|
|
6
|
-
return false;
|
|
7
|
-
let result = 0;
|
|
8
|
-
for (let i = 0; i < a.length; i++) {
|
|
9
|
-
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
10
|
-
}
|
|
11
|
-
return result === 0;
|
|
12
|
-
};
|
|
4
|
+
import { timingSafeStringEqual } from '../utils/hmac.js';
|
|
13
5
|
/**
|
|
14
6
|
* Guards the remote job inbox. Fails closed: an unset secret rejects every
|
|
15
7
|
* caller, so the routes are never open just because the deployment forgot to
|
|
@@ -20,7 +12,7 @@ export const remoteJobsSecret = pikkuMiddleware(async ({ variables }, { http },
|
|
|
20
12
|
const provided = http?.request?.header(REMOTE_JOBS_SECRET_HEADER);
|
|
21
13
|
if (!expected ||
|
|
22
14
|
typeof provided !== 'string' ||
|
|
23
|
-
!
|
|
15
|
+
!timingSafeStringEqual(provided, expected)) {
|
|
24
16
|
throw new UnauthorizedError('invalid dispatch secret');
|
|
25
17
|
}
|
|
26
18
|
return next();
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { PikkuWiringTypes } from './types/core.types.js';
|
|
2
2
|
import type { CorePikkuMiddleware, CorePikkuMiddlewareGroup, MiddlewareMetadata } from './middleware/middleware.types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runs `middlewares` as an onion around `main`, ordered by priority (stable
|
|
5
|
+
* within a priority), and returns `main`'s result. A middleware that does not
|
|
6
|
+
* call `next` stops the chain: `main` is never run and the result is
|
|
7
|
+
* `undefined`.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
3
10
|
export declare const runMiddleware: <Middleware extends CorePikkuMiddleware<any, any>>(services: Parameters<Middleware>[0], wire: Parameters<Middleware>[1], middlewares: readonly Middleware[], main?: () => Promise<unknown>) => Promise<unknown>;
|
|
4
11
|
/**
|
|
5
12
|
* Registers tag-scoped middleware for any wiring carrying the tag. Wrap in a
|