@pikku/core 0.12.143 → 0.12.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/analytics.d.ts +14 -0
- package/dist/analytics/analytics.js +14 -0
- package/dist/analytics/analytics.types.d.ts +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +1 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +1 -0
- package/dist/analytics/mint-cookie.d.ts +1 -0
- package/dist/{wirings/channel/channel-middleware-runner.d.ts → channel-middleware-runner.d.ts} +17 -3
- package/dist/{wirings/channel/channel-middleware-runner.js → channel-middleware-runner.js} +24 -8
- package/dist/classification/data-classification.d.ts +13 -0
- package/dist/classification/secret-value.d.ts +7 -0
- package/dist/classification/secret-value.js +7 -0
- package/dist/crypto-utils.d.ts +93 -0
- package/dist/crypto-utils.js +92 -0
- package/dist/dev/hot-reload.d.ts +16 -0
- package/dist/dev/hot-reload.js +16 -1
- package/dist/dev/module-runner.js +7 -3
- package/dist/dev/reload-meta.js +1 -1
- package/dist/errors/error-handler.d.ts +9 -0
- package/dist/errors/error-handler.js +8 -0
- package/dist/errors/errors.d.ts +219 -0
- package/dist/errors/errors.js +227 -0
- package/dist/errors/serialized-error.d.ts +4 -0
- package/dist/function/abort-scope.d.ts +5 -0
- package/dist/function/function-meta.types.d.ts +20 -0
- package/dist/function/function-runner.d.ts +41 -0
- package/dist/function/function-runner.js +57 -11
- package/dist/function/functions.types.d.ts +59 -0
- package/dist/function/functions.types.js +23 -0
- package/dist/function/list.types.d.ts +4 -0
- package/dist/lifecycle.d.ts +12 -1
- package/dist/lifecycle.js +12 -1
- package/dist/middleware/addon-scope-cap.d.ts +4 -0
- package/dist/middleware/addon-scope-cap.js +7 -3
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.js +5 -13
- package/dist/middleware/auth-cookie.js +3 -3
- package/dist/middleware/middleware-factories.d.ts +17 -0
- package/dist/middleware/middleware-factories.js +17 -0
- package/dist/middleware/middleware.types.d.ts +23 -0
- package/dist/middleware/remote-auth.d.ts +15 -0
- package/dist/middleware/remote-auth.js +18 -3
- package/dist/middleware/remote-jobs-secret.js +2 -10
- package/dist/middleware-runner.d.ts +7 -0
- package/dist/middleware-runner.js +23 -7
- package/dist/permissions.d.ts +13 -0
- package/dist/permissions.js +13 -0
- package/dist/pikku-state.d.ts +49 -0
- package/dist/pikku-state.js +49 -0
- package/dist/remote.js +20 -5
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +36 -0
- package/dist/services/agent-run-state-service.d.ts +8 -0
- package/dist/services/agent-runner-service.d.ts +24 -0
- package/dist/services/agent-storage-service.d.ts +8 -0
- package/dist/services/ai-embedding-service.d.ts +4 -0
- package/dist/services/audit-service.d.ts +48 -0
- package/dist/services/audit-service.js +22 -0
- package/dist/services/content-service.d.ts +34 -0
- package/dist/services/credential-wire-service.d.ts +9 -0
- package/dist/services/credential-wire-service.js +9 -0
- package/dist/services/deployment-service.d.ts +14 -0
- package/dist/services/email-service.d.ts +20 -0
- package/dist/services/email-template.d.ts +24 -0
- package/dist/services/email-template.js +12 -0
- package/dist/services/file-scenario-run-store.d.ts +5 -0
- package/dist/services/file-scenario-run-store.js +4 -0
- package/dist/services/gateway-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.js +5 -0
- package/dist/services/in-memory-lease-service.d.ts +5 -0
- package/dist/services/in-memory-lease-service.js +5 -0
- package/dist/services/in-memory-session-store.d.ts +4 -0
- package/dist/services/in-memory-session-store.js +4 -0
- package/dist/services/incoming-webhook-queue.d.ts +2 -0
- package/dist/services/incoming-webhook-queue.js +2 -0
- package/dist/services/incoming-webhook-service.d.ts +9 -1
- package/dist/services/incoming-webhook-service.js +1 -1
- package/dist/services/index.d.ts +1 -5
- package/dist/services/index.js +1 -5
- package/dist/services/jwt-service.d.ts +8 -0
- package/dist/services/lease-service.d.ts +5 -0
- package/dist/services/lease-service.js +1 -0
- package/dist/services/local-content-request-handler.d.ts +20 -0
- package/dist/services/local-content-request-handler.js +11 -0
- package/dist/services/local-content.d.ts +45 -0
- package/dist/services/local-content.js +35 -0
- package/dist/services/local-credential-service.d.ts +5 -0
- package/dist/services/local-credential-service.js +5 -0
- package/dist/services/local-email-service.d.ts +7 -0
- package/dist/services/local-email-service.js +7 -0
- package/dist/services/local-secrets.d.ts +8 -0
- package/dist/services/local-secrets.js +8 -0
- package/dist/services/local-variables.d.ts +6 -0
- package/dist/services/local-variables.js +6 -0
- package/dist/services/logger.d.ts +4 -0
- package/dist/services/logger.js +4 -0
- package/dist/services/meta-service.d.ts +38 -0
- package/dist/services/meta-service.js +6 -0
- package/dist/services/queue-webhook-service.d.ts +19 -0
- package/dist/services/queue-webhook-service.js +19 -0
- package/dist/services/remote-jobs.d.ts +8 -13
- package/dist/services/remote-jobs.js +3 -54
- package/dist/services/scenario-cookie-jar.d.ts +4 -0
- package/dist/services/scheduler-service.d.ts +13 -0
- package/dist/services/scheduler-service.js +8 -0
- package/dist/services/schema-service.d.ts +9 -0
- package/dist/services/scope-service.d.ts +10 -0
- package/dist/services/scoped-secret-service.d.ts +5 -0
- package/dist/services/scoped-secret-service.js +5 -0
- package/dist/services/secret-host-binding.d.ts +5 -0
- package/dist/services/secret-host-binding.js +5 -0
- package/dist/services/secret-service.d.ts +19 -1
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +6 -0
- package/dist/services/session-store.d.ts +5 -0
- package/dist/services/stub-tracker.d.ts +1 -0
- package/dist/services/temporary-file-service.d.ts +9 -0
- package/dist/services/temporary-file-service.js +9 -0
- package/dist/services/trigger-service.d.ts +4 -0
- package/dist/services/trigger-source-store.d.ts +13 -0
- package/dist/services/trigger-source-store.js +7 -0
- package/dist/services/typed-credential-service.d.ts +6 -0
- package/dist/services/typed-credential-service.js +5 -0
- package/dist/services/typed-secret-service.d.ts +12 -0
- package/dist/services/typed-secret-service.js +11 -0
- package/dist/services/typed-variables-service.d.ts +1 -0
- package/dist/services/user-session-service.d.ts +31 -1
- package/dist/services/user-session-service.js +29 -3
- package/dist/services/v8-coverage-service.d.ts +27 -0
- package/dist/services/v8-coverage-service.js +5 -0
- package/dist/services/variables-service.d.ts +8 -0
- package/dist/services/virtual-user-sign-in.d.ts +1 -0
- package/dist/services/virtual-user-statement.d.ts +8 -0
- package/dist/services/virtual-user-statement.js +4 -0
- package/dist/services/webhook-service.d.ts +25 -0
- package/dist/services/webhook-service.js +15 -0
- package/dist/services/workflow-service.d.ts +6 -0
- package/dist/test-utils.js +1 -1
- package/dist/testing/service-tests.d.ts +4 -0
- package/dist/time-utils.d.ts +15 -0
- package/dist/time-utils.js +14 -0
- package/dist/types/core.types.d.ts +80 -0
- package/dist/types/state.types.d.ts +4 -0
- package/dist/utils/hmac.d.ts +3 -0
- package/dist/utils/safe-fetch.d.ts +14 -0
- package/dist/utils/safe-fetch.js +13 -0
- package/dist/utils/stable-stringify.d.ts +11 -0
- package/dist/utils/stable-stringify.js +33 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +22 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +7 -0
- package/dist/wirings/addon/define-screens.d.ts +2 -0
- package/dist/wirings/addon/remote-addon-auth.d.ts +9 -0
- package/dist/wirings/addon/remote-addon-auth.js +5 -0
- package/dist/wirings/addon/wire-addon.d.ts +4 -0
- package/dist/wirings/addon/wire-remote-addon.d.ts +1 -0
- package/dist/wirings/agent/agent-agui.d.ts +14 -5
- package/dist/wirings/agent/agent-agui.js +17 -6
- package/dist/wirings/agent/agent-helpers.d.ts +61 -1
- package/dist/wirings/agent/agent-helpers.js +62 -2
- package/dist/wirings/agent/agent-interrupt.d.ts +5 -0
- package/dist/wirings/agent/agent-output.d.ts +20 -0
- package/dist/wirings/agent/agent-output.js +69 -0
- package/dist/wirings/agent/agent-prepare.d.ts +41 -0
- package/dist/wirings/agent/agent-prepare.js +38 -2
- package/dist/wirings/agent/agent-registry.d.ts +8 -0
- package/dist/wirings/agent/agent-registry.js +10 -4
- package/dist/wirings/agent/agent-runner.d.ts +33 -0
- package/dist/wirings/agent/agent-runner.js +40 -7
- package/dist/wirings/agent/agent-stream.d.ts +30 -0
- package/dist/wirings/agent/agent-stream.js +33 -11
- package/dist/wirings/agent/agent.types.d.ts +43 -0
- package/dist/wirings/agent/voice-input.d.ts +12 -0
- package/dist/wirings/agent/voice-input.js +12 -0
- package/dist/wirings/agent/voice-output.d.ts +14 -0
- package/dist/wirings/agent/voice-output.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.js +1 -2
- package/dist/wirings/agent-scorer/agent-scorer-registry.d.ts +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.d.ts +1 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.js +1 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +7 -0
- package/dist/wirings/channel/channel-common.js +1 -1
- package/dist/wirings/channel/channel-rpc.types.d.ts +5 -0
- package/dist/wirings/channel/channel-runner.d.ts +22 -0
- package/dist/wirings/channel/channel-runner.js +22 -0
- package/dist/wirings/channel/channel-store.d.ts +8 -0
- package/dist/wirings/channel/channel-store.js +7 -0
- package/dist/wirings/channel/channel.types.d.ts +18 -0
- package/dist/wirings/channel/define-channel-routes.d.ts +5 -0
- package/dist/wirings/channel/define-channel-routes.js +5 -0
- package/dist/wirings/channel/eventhub-service.d.ts +9 -0
- package/dist/wirings/channel/eventhub-store.d.ts +1 -0
- package/dist/wirings/channel/eventhub-store.js +1 -0
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/index.js +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -0
- package/dist/wirings/channel/local/local-channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +13 -0
- package/dist/wirings/channel/local/local-channel-runner.js +13 -0
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +1 -0
- package/dist/wirings/channel/local/local-eventhub-service.js +1 -0
- package/dist/wirings/channel/log-channels.d.ts +1 -0
- package/dist/wirings/channel/log-channels.js +1 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +5 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +5 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +32 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +31 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +8 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +8 -0
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +43 -0
- package/dist/wirings/cli/cli-runner.js +43 -0
- package/dist/wirings/cli/cli.types.d.ts +4 -0
- package/dist/wirings/cli/command-parser.d.ts +13 -0
- package/dist/wirings/cli/command-parser.js +16 -0
- package/dist/wirings/credential/credential-overrides.d.ts +1 -0
- package/dist/wirings/credential/credential.types.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.js +7 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +1 -0
- package/dist/wirings/flag/flag.types.d.ts +3 -0
- package/dist/wirings/gateway/gateway-runner.d.ts +23 -0
- package/dist/wirings/gateway/gateway-runner.js +23 -0
- package/dist/wirings/gateway/gateway.types.d.ts +3 -0
- package/dist/wirings/gateway/local-gateway-service.d.ts +10 -0
- package/dist/{services → wirings/gateway}/local-gateway-service.js +6 -2
- package/dist/wirings/http/http-routes.d.ts +21 -0
- package/dist/wirings/http/http-routes.js +11 -0
- package/dist/wirings/http/http-runner.d.ts +71 -0
- package/dist/wirings/http/http-runner.js +73 -5
- package/dist/wirings/http/http.types.d.ts +27 -0
- package/dist/wirings/http/index.d.ts +1 -0
- package/dist/wirings/http/index.js +1 -0
- package/dist/wirings/http/log-http-routes.d.ts +1 -0
- package/dist/wirings/http/log-http-routes.js +1 -0
- package/dist/wirings/http/merge-request-data.d.ts +12 -0
- package/dist/wirings/http/merge-request-data.js +42 -0
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.js +3 -32
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +1 -0
- package/dist/wirings/http/routers/http-router.d.ts +6 -0
- package/dist/wirings/http/routers/http-router.js +6 -0
- package/dist/wirings/http/web-request.d.ts +17 -0
- package/dist/wirings/http/web-request.js +17 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +7 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.js +7 -0
- package/dist/wirings/mcp/mcp-runner.d.ts +63 -0
- package/dist/wirings/mcp/mcp-runner.js +62 -0
- package/dist/wirings/mcp/mcp.types.d.ts +12 -0
- package/dist/wirings/node/node.types.d.ts +4 -0
- package/dist/wirings/oauth2/oauth2.types.d.ts +2 -0
- package/dist/{services → wirings/queue}/in-memory-queue-service.d.ts +9 -1
- package/dist/{services → wirings/queue}/in-memory-queue-service.js +9 -1
- package/dist/wirings/queue/index.d.ts +1 -0
- package/dist/wirings/queue/index.js +1 -0
- package/dist/wirings/queue/queue-identity.js +2 -14
- package/dist/wirings/queue/queue-runner.d.ts +37 -0
- package/dist/wirings/queue/queue-runner.js +37 -0
- package/dist/wirings/queue/queue.types.d.ts +35 -0
- package/dist/wirings/queue/register-queue-helper.d.ts +12 -0
- package/dist/wirings/queue/register-queue-helper.js +11 -0
- package/dist/wirings/queue/remote-queue-job.d.ts +11 -0
- package/dist/wirings/queue/remote-queue-job.js +41 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -0
- package/dist/wirings/role/role.types.d.ts +3 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +24 -0
- package/dist/wirings/rpc/rpc-runner.js +37 -2
- package/dist/wirings/rpc/rpc-types.d.ts +2 -0
- package/dist/wirings/scheduler/index.d.ts +1 -0
- package/dist/wirings/scheduler/index.js +1 -0
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -0
- package/dist/wirings/scheduler/log-schedulers.js +1 -0
- package/dist/wirings/scheduler/remote-scheduled-job.d.ts +11 -0
- package/dist/wirings/scheduler/remote-scheduled-job.js +20 -0
- package/dist/wirings/scheduler/scheduler-runner.d.ts +29 -0
- package/dist/wirings/scheduler/scheduler-runner.js +28 -0
- package/dist/wirings/scheduler/scheduler.types.d.ts +3 -0
- package/dist/wirings/scope/scope.types.d.ts +5 -0
- package/dist/wirings/secret/index.d.ts +2 -2
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +26 -1
- package/dist/wirings/secret/secret.types.js +1 -0
- package/dist/wirings/secret/validate-secret-definitions.d.ts +8 -0
- package/dist/wirings/secret/validate-secret-definitions.js +15 -0
- package/dist/wirings/trigger/in-memory-trigger-service.d.ts +11 -0
- package/dist/{services → wirings/trigger}/in-memory-trigger-service.js +10 -3
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +8 -3
- package/dist/wirings/trigger/pikku-trigger-service.js +14 -3
- package/dist/wirings/trigger/trigger-runner.d.ts +27 -2
- package/dist/wirings/trigger/trigger-runner.js +35 -2
- package/dist/wirings/trigger/trigger.types.d.ts +26 -4
- package/dist/wirings/trigger/webhook-source-runner.d.ts +24 -0
- package/dist/wirings/trigger/webhook-source-runner.js +19 -0
- package/dist/wirings/trigger/webhook-source.types.d.ts +12 -2
- package/dist/wirings/trigger/webhook-source.types.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +7 -0
- package/dist/wirings/variable/validate-variable-definitions.js +7 -0
- package/dist/wirings/variable/variable.types.d.ts +7 -0
- package/dist/wirings/virtual-user/conversation/conversation.types.d.ts +5 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +6 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.js +1 -1
- package/dist/{services → wirings/virtual-user}/http-virtual-users.d.ts +4 -3
- package/dist/{services → wirings/virtual-user}/http-virtual-users.js +6 -6
- package/dist/wirings/virtual-user/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.js +1 -1
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +2 -1
- package/dist/wirings/virtual-user/run-virtual-user.js +1 -14
- package/dist/wirings/virtual-user/virtual-user-declaration.types.d.ts +4 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +10 -1
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.js +1 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +1 -0
- package/dist/wirings/webhook/define-outgoing-webhook.d.ts +20 -0
- package/dist/wirings/webhook/define-outgoing-webhook.js +9 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +8 -4
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +7 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +7 -0
- package/dist/wirings/workflow/feature.d.ts +12 -0
- package/dist/wirings/workflow/feature.js +12 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +5 -0
- package/dist/wirings/workflow/graph/graph-node.js +5 -0
- package/dist/wirings/workflow/graph/template.d.ts +6 -0
- package/dist/wirings/workflow/graph/template.js +5 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +12 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +10 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +11 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +1 -0
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.d.ts +8 -3
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.js +9 -4
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +1 -1
- package/dist/wirings/workflow/pikku-scenario-service.js +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +1 -0
- package/dist/wirings/workflow/pikku-workflow-service.js +1 -0
- package/dist/wirings/workflow/run-timeline.d.ts +21 -0
- package/dist/wirings/workflow/run-timeline.js +15 -7
- package/dist/wirings/workflow/scenario-coverage.d.ts +1 -0
- package/dist/wirings/workflow/scenario-poll.d.ts +1 -0
- package/dist/wirings/workflow/scenario-prose.d.ts +6 -0
- package/dist/wirings/workflow/scenario-prose.js +6 -0
- package/dist/wirings/workflow/scenario-run.types.d.ts +3 -0
- package/dist/wirings/workflow/scenario-step.types.d.ts +1 -0
- package/dist/wirings/workflow/scenario-step.types.js +1 -0
- package/dist/wirings/workflow/scenario-surface.js +1 -13
- package/dist/wirings/workflow/scenario.types.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +6 -0
- package/dist/wirings/workflow/workflow-constants.d.ts +7 -1
- package/dist/wirings/workflow/workflow-constants.js +10 -1
- package/dist/wirings/workflow/workflow-errors.d.ts +13 -0
- package/dist/wirings/workflow/workflow-errors.js +13 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +4 -0
- package/dist/wirings/workflow/workflow-invocation-id.js +4 -0
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +3 -0
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +1 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +1 -0
- package/dist/wirings/workflow/workflow-status-stream.d.ts +1 -0
- package/dist/wirings/workflow/workflow-unwind-plan.js +2 -7
- package/dist/wirings/workflow/workflow.types.d.ts +40 -0
- package/package.json +26 -9
- package/CHANGELOG.md +0 -6978
- package/dist/services/in-memory-trigger-service.d.ts +0 -4
- package/dist/services/local-gateway-service.d.ts +0 -6
- package/dist/utils/hash.d.ts +0 -2
- package/dist/utils/hash.js +0 -23
- package/knowledge/decisions/index.md +0 -19
- package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +0 -29
- package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +0 -29
- package/knowledge/decisions/internals/a-held-run-is-woken-later-not-retried.md +0 -28
- package/knowledge/decisions/internals/a-latency-budget-is-asserted-by-its-cause.md +0 -32
- package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-agentrunstate-too.md +0 -22
- package/knowledge/decisions/internals/a-reset-suite-makes-the-dev-seed-the-fixture.md +0 -50
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +0 -20
- package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +0 -21
- package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +0 -22
- package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +0 -28
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +0 -49
- package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +0 -32
- package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +0 -66
- package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +0 -24
- package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +0 -21
- package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +0 -34
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +0 -65
- package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +0 -49
- package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +0 -45
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +0 -26
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +0 -32
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +0 -33
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +0 -28
- package/knowledge/decisions/internals/agent-agui-bridge-obeys-the-client-ordering-contract.md +0 -29
- package/knowledge/decisions/internals/agent-audio-chunks-carry-the-format-the-provider-returned.md +0 -20
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +0 -21
- package/knowledge/decisions/internals/agent-credential-suspensions-hide-the-tool-result.md +0 -26
- package/knowledge/decisions/internals/agent-delegate-and-supervise-hide-different-text.md +0 -26
- package/knowledge/decisions/internals/agent-llm-tool-arguments-have-nulls-stripped.md +0 -23
- package/knowledge/decisions/internals/agent-model-config-stays-a-single-resolution-seam.md +0 -25
- package/knowledge/decisions/internals/agent-onerror-hooks-cannot-change-the-failure.md +0 -22
- package/knowledge/decisions/internals/agent-runner-methods-must-keep-their-receiver.md +0 -22
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +0 -22
- package/knowledge/decisions/internals/agent-stream-persistence-is-best-effort.md +0 -27
- package/knowledge/decisions/internals/agent-sub-agents-inherit-the-parent-context-block.md +0 -26
- package/knowledge/decisions/internals/agent-tool-execute-failures-are-logged-unconditionally.md +0 -25
- package/knowledge/decisions/internals/agent-voice-input-transcribes-audio-parts-in-place.md +0 -22
- package/knowledge/decisions/internals/agent-working-memory-is-persisted-only-when-valid.md +0 -25
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +0 -39
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +0 -23
- package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +0 -27
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +0 -25
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +0 -22
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +0 -20
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +0 -22
- package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +0 -26
- package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +0 -66
- package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +0 -22
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +0 -30
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +0 -31
- package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +0 -33
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +0 -29
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +0 -28
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +0 -27
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +0 -28
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +0 -34
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +0 -29
- package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +0 -84
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +0 -41
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +0 -44
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +0 -39
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +0 -42
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +0 -39
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +0 -43
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +0 -38
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +0 -44
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +0 -27
- package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +0 -22
- package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +0 -28
- package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +0 -24
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +0 -32
- package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +0 -43
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +0 -28
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +0 -31
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +0 -26
- package/knowledge/decisions/internals/global-middleware-resolves-from-the-root-namespace-too.md +0 -32
- package/knowledge/decisions/internals/hot-reload-reads-the-changed-source-never-a-compiled-copy.md +0 -38
- package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +0 -26
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +0 -32
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +0 -28
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +0 -30
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +0 -26
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +0 -28
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +0 -32
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +0 -26
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +0 -25
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +0 -26
- package/knowledge/decisions/internals/index.md +0 -182
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +0 -25
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +0 -26
- package/knowledge/decisions/internals/mcp-wire-names-are-assigned-over-the-whole-registry.md +0 -39
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +0 -24
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +0 -53
- package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +0 -21
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +0 -28
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +0 -27
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +0 -31
- package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +0 -30
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +0 -32
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +0 -31
- package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +0 -24
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +0 -26
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +0 -27
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +0 -48
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +0 -30
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +0 -28
- package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +0 -34
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +0 -24
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +0 -26
- package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +0 -43
- package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +0 -22
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +0 -30
- package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +0 -83
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +0 -29
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +0 -27
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +0 -40
- package/knowledge/decisions/internals/the-mcp-handshake-is-challenged-only-when-every-target-is-gated.md +0 -29
- package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +0 -40
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +0 -40
- package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +0 -24
- package/knowledge/decisions/internals/the-runner-resolves-wire-services-itself.md +0 -31
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +0 -26
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +0 -25
- package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +0 -21
- package/knowledge/decisions/internals/the-virtual-user-prompt-says-json-because-of-json-object-mode.md +0 -22
- package/knowledge/decisions/internals/the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md +0 -28
- package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +0 -22
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +0 -25
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +0 -33
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +0 -26
- package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +0 -43
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +0 -115
- package/knowledge/decisions/internals/virtual-user-conversation-drives-the-target-through-a-transport-seam.md +0 -24
- package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +0 -25
- package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +0 -23
- package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +0 -21
- package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +0 -30
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +0 -24
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +0 -26
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +0 -25
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +0 -58
- package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +0 -35
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +0 -34
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +0 -42
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +0 -38
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +0 -29
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +0 -42
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +0 -25
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +0 -29
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +0 -43
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +0 -29
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +0 -42
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +0 -33
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +0 -32
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +0 -31
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +0 -39
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +0 -29
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +0 -33
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +0 -37
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +0 -54
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +0 -43
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +0 -32
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +0 -18
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +0 -34
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +0 -29
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +0 -33
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +0 -34
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +0 -34
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +0 -38
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +0 -30
- package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +0 -26
- package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +0 -20
- package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +0 -23
- package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +0 -16
- package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +0 -26
- package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +0 -32
- package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +0 -27
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +0 -28
- package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +0 -33
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +0 -37
- package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +0 -33
- package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +0 -33
- package/knowledge/decisions/security/a-public-function-says-so-with-auth-false.md +0 -34
- package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +0 -25
- package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +0 -52
- package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +0 -27
- package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +0 -26
- package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +0 -25
- package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +0 -29
- package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +0 -25
- package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +0 -37
- package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +0 -24
- package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +0 -29
- package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +0 -30
- package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +0 -38
- package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +0 -23
- package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +0 -41
- package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +0 -25
- package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +0 -32
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +0 -50
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +0 -43
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +0 -52
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +0 -46
- package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +0 -20
- package/knowledge/decisions/security/agent-approval-forwarding-requires-a-symbol-brand.md +0 -27
- package/knowledge/decisions/security/agent-credential-requests-are-symbol-branded.md +0 -37
- package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +0 -31
- package/knowledge/decisions/security/agent-ownership-failures-never-echo-the-resource.md +0 -23
- package/knowledge/decisions/security/agent-resume-re-runs-the-authorization-gate.md +0 -22
- package/knowledge/decisions/security/agent-sessionless-deployments-have-no-thread-ownership.md +0 -39
- package/knowledge/decisions/security/agent-thread-ownership-composes-the-session-principal.md +0 -30
- package/knowledge/decisions/security/agent-tool-filtering-reads-the-live-function-config.md +0 -24
- package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +0 -26
- package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +0 -33
- package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +0 -16
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +0 -33
- package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +0 -26
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +0 -59
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +0 -30
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +0 -52
- package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +0 -38
- package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +0 -31
- package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +0 -18
- package/knowledge/decisions/security/an-mcp-refusal-is-decided-before-dispatch.md +0 -48
- package/knowledge/decisions/security/an-oauth2-credential-is-read-by-its-account-row.md +0 -40
- package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +0 -32
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +0 -24
- package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +0 -24
- package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +0 -26
- package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +0 -27
- package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +0 -25
- package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +0 -18
- package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +0 -29
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +0 -84
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +0 -39
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +0 -37
- package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +0 -22
- package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +0 -29
- package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +0 -27
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +0 -41
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +0 -30
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +0 -40
- package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +0 -25
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +0 -33
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +0 -46
- package/knowledge/decisions/security/index.md +0 -135
- package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +0 -21
- package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +0 -38
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +0 -27
- package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +0 -18
- package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +0 -22
- package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +0 -26
- package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +0 -24
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +0 -40
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +0 -31
- package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +0 -35
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +0 -69
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +0 -39
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +0 -34
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +0 -55
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +0 -30
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +0 -28
- package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +0 -31
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +0 -34
- package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +0 -22
- package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +0 -34
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +0 -37
- package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +0 -26
- package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +0 -24
- package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +0 -16
- package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +0 -21
- package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +0 -24
- package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +0 -34
- package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +0 -16
- package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +0 -29
- package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +0 -23
- package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +0 -25
- package/knowledge/decisions/security/virtual-user-conversation-missing-approval-decisions-default-to-denied.md +0 -22
- package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +0 -18
- package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +0 -25
- package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +0 -42
- package/knowledge/decisions/security/virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +0 -29
- package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +0 -29
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +0 -25
- package/knowledge/decisions/security/wire-addon-expose-selects-the-rpc-surface.md +0 -51
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +0 -40
- package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +0 -18
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +0 -31
- package/knowledge/decisions/security/workflow-virtual-user-steps-always-use-the-real-transport.md +0 -34
- package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +0 -18
- package/knowledge/index.md +0 -24
- package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +0 -24
- package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +0 -35
- package/knowledge/questions/dev-quick-login-as-impersonation.md +0 -25
- package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +0 -26
- package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +0 -27
- package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +0 -26
- package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +0 -26
- package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +0 -34
- package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +0 -20
- package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +0 -24
- package/knowledge/questions/does-the-store-session-match-the-other-two.md +0 -19
- package/knowledge/questions/index.md +0 -41
- package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +0 -21
- package/knowledge/questions/live-scheduled-tests-may-write.md +0 -19
- package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +0 -23
- package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +0 -32
- package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +0 -25
- package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +0 -23
- package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +0 -35
- package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +0 -23
- package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +0 -27
- package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +0 -26
- package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +0 -20
- package/knowledge/questions/staging-impersonation-rules.md +0 -27
- package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +0 -44
- package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +0 -33
- package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +0 -20
- package/knowledge/questions/what-an-impersonated-session-carries.md +0 -22
- package/run-tests.sh +0 -68
- package/scripts/generate-api-report.d.mts +0 -1
- package/scripts/generate-api-report.mjs +0 -96
- package/scripts/generate-api-report.mts +0 -333
- package/src/public-surface.json +0 -637
- package/src/public-surface.json.README +0 -43
- /package/dist/{function/compensation-name.d.ts → compensation-name.d.ts} +0 -0
- /package/dist/{function/compensation-name.js → compensation-name.js} +0 -0
|
@@ -3,4 +3,18 @@ import type { Logger } from '../services/logger.js';
|
|
|
3
3
|
import type { AnalyticsEventBase, AnalyticsEventInput, AnalyticsIdentityResolver, AnalyticsLog, AnalyticsService } from './analytics.types.js';
|
|
4
4
|
/** Removes the discriminator, so `props` is free of the series key. */
|
|
5
5
|
export declare const flattenAnalyticsEvent: (event: AnalyticsEventBase, at?: number) => AnalyticsEventInput;
|
|
6
|
+
/**
|
|
7
|
+
* Creates the per-invocation `analytics` log handed to a function.
|
|
8
|
+
*
|
|
9
|
+
* Events are buffered and written to `service` in one batch on `flush()`/`close()`.
|
|
10
|
+
* Identity is stamped from the wire's session (never from the event payload), merged
|
|
11
|
+
* with whatever `resolveIdentity` returns. A failed write is logged as a warning and
|
|
12
|
+
* dropped, so analytics can never fail the request.
|
|
13
|
+
*
|
|
14
|
+
* @param service - The sink the batch is written to.
|
|
15
|
+
* @param wire - The invocation's wire; supplies session, trace and function ids.
|
|
16
|
+
* @param logger - Fallback logger when the wire carries none.
|
|
17
|
+
* @param resolveIdentity - Adds browser-originated ids and consent to each record.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
6
20
|
export declare const createInvocationAnalytics: (service: AnalyticsService, wire: PikkuWire<any, any, any, CoreUserSession>, logger?: Logger, resolveIdentity?: AnalyticsIdentityResolver) => AnalyticsLog;
|
|
@@ -55,4 +55,18 @@ class InvocationAnalyticsLog {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates the per-invocation `analytics` log handed to a function.
|
|
60
|
+
*
|
|
61
|
+
* Events are buffered and written to `service` in one batch on `flush()`/`close()`.
|
|
62
|
+
* Identity is stamped from the wire's session (never from the event payload), merged
|
|
63
|
+
* with whatever `resolveIdentity` returns. A failed write is logged as a warning and
|
|
64
|
+
* dropped, so analytics can never fail the request.
|
|
65
|
+
*
|
|
66
|
+
* @param service - The sink the batch is written to.
|
|
67
|
+
* @param wire - The invocation's wire; supplies session, trace and function ids.
|
|
68
|
+
* @param logger - Fallback logger when the wire carries none.
|
|
69
|
+
* @param resolveIdentity - Adds browser-originated ids and consent to each record.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
58
72
|
export const createInvocationAnalytics = (service, wire, logger, resolveIdentity) => new InvocationAnalyticsLog(service, wire, logger, resolveIdentity);
|
|
@@ -11,6 +11,7 @@ export type AnalyticsEventBase = {
|
|
|
11
11
|
/** The event name, as declared in `defineAnalyticsEvents`. */
|
|
12
12
|
name: string;
|
|
13
13
|
} & Record<string, unknown>;
|
|
14
|
+
/** An event as a caller submits it: name, free-form props and an optional client timestamp (ms). */
|
|
14
15
|
export interface AnalyticsEventInput {
|
|
15
16
|
name: string;
|
|
16
17
|
props?: Record<string, unknown>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SerializeOptions } from 'cookie';
|
|
2
2
|
import type { AnalyticsIdentityResolver } from './analytics.types.js';
|
|
3
|
+
/** Options for `anonymousAnalyticsIdentity`. */
|
|
3
4
|
export interface AnonymousAnalyticsIdentityOptions {
|
|
4
5
|
/** Cookie name. Defaults to `pikku_aid`. */
|
|
5
6
|
name?: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnalyticsIdentityResolver } from './analytics.types.js';
|
|
2
|
+
/** Options for `cookieAnalyticsIdentity`: which cookies carry vendor ids and which grant consent. */
|
|
2
3
|
export interface CookieAnalyticsIdentityOptions {
|
|
3
4
|
/** Identity key to read it from, e.g. `{ gaClientId: '_ga' }`. */
|
|
4
5
|
vendorIds?: Record<string, string>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SerializeOptions } from 'cookie';
|
|
2
2
|
import type { CoreUserSession, PikkuWire } from '../types/core.types.js';
|
|
3
3
|
type AnyWire = PikkuWire<any, any, any, CoreUserSession>;
|
|
4
|
+
/** Options for `mintCookie`, including the consent purposes that gate writing it. */
|
|
4
5
|
export interface MintCookieOptions {
|
|
5
6
|
/** Cookie attributes. Long-lived and first-party is the usual shape. */
|
|
6
7
|
cookie: SerializeOptions;
|
package/dist/{wirings/channel/channel-middleware-runner.d.ts → channel-middleware-runner.d.ts}
RENAMED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import type { CoreSingletonServices, PikkuRawWire } from '
|
|
2
|
-
import type { MiddlewareMetadata } from '
|
|
3
|
-
import type { CorePikkuChannelMiddleware } from './channel.types.js';
|
|
1
|
+
import type { CoreSingletonServices, PikkuRawWire } from './types/core.types.js';
|
|
2
|
+
import type { MiddlewareMetadata } from './middleware/middleware.types.js';
|
|
3
|
+
import type { CorePikkuChannelMiddleware } from './wirings/channel/channel.types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Registers channel middleware for every channel carrying `tag`. It wraps each
|
|
6
|
+
* message the channel sends. Registering the same tag again replaces its
|
|
7
|
+
* group rather than appending to it.
|
|
8
|
+
*
|
|
9
|
+
* @returns The middleware it was given.
|
|
10
|
+
* @example snippet: addChannelMiddleware
|
|
11
|
+
*/
|
|
4
12
|
export declare const addChannelMiddleware: (tag: string, middleware: CorePikkuChannelMiddleware[], packageName?: string | null) => CorePikkuChannelMiddleware[];
|
|
5
13
|
export declare const clearChannelMiddlewareCache: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Resolves the channel middleware for one wiring: the tag and named middleware
|
|
16
|
+
* its metadata inherits, then the wiring's own, de-duplicated. The inherited
|
|
17
|
+
* part is cached per wiring.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
6
20
|
export declare const combineChannelMiddleware: (wireType: string, uid: string, { wireInheritedChannelMiddleware, wireChannelMiddleware, packageName, }?: {
|
|
7
21
|
wireInheritedChannelMiddleware?: MiddlewareMetadata[];
|
|
8
22
|
wireChannelMiddleware?: CorePikkuChannelMiddleware[];
|
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import { pikkuState } from '
|
|
2
|
-
import { freezeDedupe, getTagGroups } from '
|
|
1
|
+
import { pikkuState } from './pikku-state.js';
|
|
2
|
+
import { freezeDedupe, getTagGroups } from './utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Registers channel middleware for every channel carrying `tag`. It wraps each
|
|
5
|
+
* message the channel sends. Registering the same tag again replaces its
|
|
6
|
+
* group rather than appending to it.
|
|
7
|
+
*
|
|
8
|
+
* @returns The middleware it was given.
|
|
9
|
+
* @example snippet: addChannelMiddleware
|
|
10
|
+
*/
|
|
3
11
|
export const addChannelMiddleware = (tag, middleware, packageName = null) => {
|
|
4
12
|
const tagGroups = pikkuState(packageName, 'channelMiddleware', 'tagGroup');
|
|
5
13
|
tagGroups[tag] = middleware;
|
|
6
14
|
return middleware;
|
|
7
15
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
16
|
+
/** Like `getMiddlewareByName`: the package's own namespace, then the application's. */
|
|
17
|
+
const getChannelMiddlewareByName = (name, packageName) => {
|
|
18
|
+
const own = pikkuState(packageName, 'misc', 'channelMiddleware')[name]?.[0];
|
|
19
|
+
if (own || packageName === null)
|
|
20
|
+
return own;
|
|
21
|
+
return pikkuState(null, 'misc', 'channelMiddleware')[name]?.[0];
|
|
12
22
|
};
|
|
13
23
|
const channelMiddlewareCache = {};
|
|
14
24
|
export const clearChannelMiddlewareCache = () => {
|
|
@@ -16,8 +26,14 @@ export const clearChannelMiddlewareCache = () => {
|
|
|
16
26
|
delete channelMiddlewareCache[key];
|
|
17
27
|
}
|
|
18
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolves the channel middleware for one wiring: the tag and named middleware
|
|
31
|
+
* its metadata inherits, then the wiring's own, de-duplicated. The inherited
|
|
32
|
+
* part is cached per wiring.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
19
35
|
export const combineChannelMiddleware = (wireType, uid, { wireInheritedChannelMiddleware, wireChannelMiddleware, packageName = null, } = {}) => {
|
|
20
|
-
const cacheKey = `${wireType}:${uid}`;
|
|
36
|
+
const cacheKey = `${packageName ?? ''}\0${wireType}:${uid}`;
|
|
21
37
|
let inherited = channelMiddlewareCache[cacheKey];
|
|
22
38
|
if (!inherited) {
|
|
23
39
|
const resolved = [];
|
|
@@ -30,7 +46,7 @@ export const combineChannelMiddleware = (wireType, uid, { wireInheritedChannelMi
|
|
|
30
46
|
}
|
|
31
47
|
}
|
|
32
48
|
else if (meta.type === 'wire') {
|
|
33
|
-
const middleware = getChannelMiddlewareByName(meta.name);
|
|
49
|
+
const middleware = getChannelMiddlewareByName(meta.name, packageName);
|
|
34
50
|
if (middleware) {
|
|
35
51
|
resolved.push(middleware);
|
|
36
52
|
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brands a value as private: personal data that may be stored but must not leave in a response unchecked.
|
|
3
|
+
* The brand is optional, so plain values are still assignable; the inspector reads it statically.
|
|
4
|
+
*/
|
|
1
5
|
export type Private<T> = T & {
|
|
2
6
|
readonly __classification__?: 'private';
|
|
3
7
|
};
|
|
8
|
+
/** Brands a value as personally identifiable information. Same erasable, optional brand as `Private<T>`. */
|
|
4
9
|
export type Pii<T> = T & {
|
|
5
10
|
readonly __classification__?: 'pii';
|
|
6
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Brands a value as secret (credentials, tokens). Same erasable, optional brand as `Private<T>`;
|
|
14
|
+
* `SecretValue.reveal()` returns this so the inspector can follow a revealed secret.
|
|
15
|
+
*/
|
|
7
16
|
export type Secret<T> = T & {
|
|
8
17
|
readonly __classification__?: 'secret';
|
|
9
18
|
};
|
|
19
|
+
/** Sensitivity level of a value or column, from least to most sensitive. */
|
|
10
20
|
export type Classification = 'public' | 'private' | 'pii' | 'secret';
|
|
21
|
+
/** How a column is rewritten when data is anonymized; `null` means no strategy has been chosen. */
|
|
11
22
|
export type AnonymizeStrategy = 'fake:email' | 'fake:name' | 'hash' | 'keep' | null;
|
|
12
23
|
/**
|
|
13
24
|
* How a column's bytes are represented at rest, as distinct from how sensitive
|
|
@@ -50,6 +61,7 @@ export type SealedValue = string & {
|
|
|
50
61
|
export type HashedValue = string & {
|
|
51
62
|
readonly [hashedBrand]: true;
|
|
52
63
|
};
|
|
64
|
+
/** One column's entry in the classification manifest: its sensitivity, anonymize strategy and at-rest form. */
|
|
53
65
|
export interface ColumnClassification {
|
|
54
66
|
classification: Classification;
|
|
55
67
|
anonymize_strategy: AnonymizeStrategy;
|
|
@@ -67,6 +79,7 @@ export interface ColumnClassification {
|
|
|
67
79
|
keyId?: string;
|
|
68
80
|
description?: string;
|
|
69
81
|
}
|
|
82
|
+
/** Per-table, per-column classification manifest, generated as `classification.gen.ts` by `pikku db migrate`. */
|
|
70
83
|
export type ClassificationManifest = {
|
|
71
84
|
version: 1;
|
|
72
85
|
tables: Record<string, Record<string, ColumnClassification>>;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { Secret } from './data-classification.js';
|
|
2
2
|
declare const secretValueBrand: unique symbol;
|
|
3
|
+
/** The placeholder a `SecretValue` serializes to in JSON and `util.inspect` output. */
|
|
3
4
|
export declare const REDACTED = "[secret]";
|
|
4
5
|
/** Runtime marker, resilient to duplicate copies of core. */
|
|
5
6
|
declare const SECRET_VALUE: unique symbol;
|
|
6
7
|
declare const NODE_INSPECT: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Thrown when a `SecretValue` is coerced to a string (template literal, concatenation, `String()`),
|
|
10
|
+
* which would otherwise write the secret out in the clear. Call `.reveal()` instead.
|
|
11
|
+
*/
|
|
7
12
|
export declare class SecretCoercionError extends Error {
|
|
8
13
|
constructor();
|
|
9
14
|
}
|
|
@@ -30,7 +35,9 @@ export declare class SecretValue<T = string> {
|
|
|
30
35
|
toString(): never;
|
|
31
36
|
[Symbol.toPrimitive](): never;
|
|
32
37
|
}
|
|
38
|
+
/** Wraps a value in a `SecretValue`, so it redacts when serialized and throws when coerced to a string. */
|
|
33
39
|
export declare const createSecretValue: <T>(value: T) => SecretValue<T>;
|
|
40
|
+
/** Whether `value` is a `SecretValue`. Uses a global symbol, so it recognises instances from duplicate copies of core. */
|
|
34
41
|
export declare const isSecretValue: (value: unknown) => value is SecretValue<unknown>;
|
|
35
42
|
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
36
43
|
type Passthrough = Function | Date | RegExp | Error | ArrayBuffer | ArrayBufferView;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
/** The placeholder a `SecretValue` serializes to in JSON and `util.inspect` output. */
|
|
1
2
|
export const REDACTED = '[secret]';
|
|
2
3
|
/** Runtime marker, resilient to duplicate copies of core. */
|
|
3
4
|
const SECRET_VALUE = Symbol.for('pikku.secretValue');
|
|
4
5
|
const NODE_INSPECT = Symbol.for('nodejs.util.inspect.custom');
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when a `SecretValue` is coerced to a string (template literal, concatenation, `String()`),
|
|
8
|
+
* which would otherwise write the secret out in the clear. Call `.reveal()` instead.
|
|
9
|
+
*/
|
|
5
10
|
export class SecretCoercionError extends Error {
|
|
6
11
|
constructor() {
|
|
7
12
|
super(`A secret was coerced to a string, which would write it out in the clear. Unwrap it deliberately with .reveal() at the point it reaches the wire.`);
|
|
@@ -42,5 +47,7 @@ export class SecretValue {
|
|
|
42
47
|
throw new SecretCoercionError();
|
|
43
48
|
}
|
|
44
49
|
}
|
|
50
|
+
/** Wraps a value in a `SecretValue`, so it redacts when serialized and throws when coerced to a string. */
|
|
45
51
|
export const createSecretValue = (value) => new SecretValue(value);
|
|
52
|
+
/** Whether `value` is a `SecretValue`. Uses a global symbol, so it recognises instances from duplicate copies of core. */
|
|
46
53
|
export const isSecretValue = (value) => typeof value === 'object' && value !== null && SECRET_VALUE in value;
|
package/dist/crypto-utils.d.ts
CHANGED
|
@@ -1,16 +1,75 @@
|
|
|
1
1
|
import type { WrappedValue } from './classification/data-classification.js';
|
|
2
|
+
/**
|
|
3
|
+
* Encrypts a JSON-serialisable value with AES-256-GCM under a key derived from
|
|
4
|
+
* `secret` by PBKDF2-SHA256 (600,000 iterations, fresh random 16-byte salt).
|
|
5
|
+
*
|
|
6
|
+
* Meant for low-entropy secrets such as passphrases; for high-entropy key material
|
|
7
|
+
* use {@link encryptWithKeyMaterial}, which skips the deliberately slow KDF.
|
|
8
|
+
*
|
|
9
|
+
* @param secret - The passphrase the key is derived from.
|
|
10
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
11
|
+
* @returns A base64url token of `salt || iv || ciphertext+tag`.
|
|
12
|
+
* @throws Error when WebCrypto is not available in the runtime.
|
|
13
|
+
*/
|
|
2
14
|
export declare const encryptJSON: (secret: string, value: unknown) => Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Reverses {@link encryptJSON}: re-derives the key from `secret` and the salt in
|
|
17
|
+
* the token, then decrypts and parses the JSON.
|
|
18
|
+
*
|
|
19
|
+
* @param secret - The passphrase the token was encrypted with.
|
|
20
|
+
* @param token - The base64url token `encryptJSON` returned.
|
|
21
|
+
* @returns The parsed value, cast to `T` without validation.
|
|
22
|
+
* @throws Error on a truncated token; the WebCrypto `OperationError` when the
|
|
23
|
+
* secret is wrong or the token was tampered with (the GCM tag fails).
|
|
24
|
+
*/
|
|
3
25
|
export declare const decryptJSON: <T>(secret: string, token: string) => Promise<T>;
|
|
4
26
|
/**
|
|
5
27
|
* Namespaces the remote-RPC session key so the same deployment secret used for
|
|
6
28
|
* another purpose derives a different key. See knowledge/crypto.md.
|
|
7
29
|
*/
|
|
8
30
|
export declare const REMOTE_SESSION_INFO = "pikku:remote-session";
|
|
31
|
+
/** Shortest key material, in characters, that the `*WithKeyMaterial` helpers accept. */
|
|
9
32
|
export declare const MIN_KEY_MATERIAL_LENGTH = 32;
|
|
33
|
+
/**
|
|
34
|
+
* Refuses key material shorter than {@link MIN_KEY_MATERIAL_LENGTH}. HKDF does no
|
|
35
|
+
* stretching, so a short secret would be brute-forceable.
|
|
36
|
+
*
|
|
37
|
+
* @param name - The secret's name, used in the error message (the value is never included).
|
|
38
|
+
* @param keyMaterial - The material to check.
|
|
39
|
+
* @throws WeakKeyMaterialError when the material is too short.
|
|
40
|
+
*/
|
|
10
41
|
export declare const assertStrongKeyMaterial: (name: string, keyMaterial: string) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Encrypts a JSON-serialisable value with AES-256-GCM under a key expanded from
|
|
44
|
+
* high-entropy key material by HKDF-SHA256, with a fresh random salt per call.
|
|
45
|
+
*
|
|
46
|
+
* `info` domain-separates the derived key, so the same deployment secret used for
|
|
47
|
+
* two purposes (e.g. {@link REMOTE_SESSION_INFO}) yields two unrelated keys.
|
|
48
|
+
*
|
|
49
|
+
* @param name - The key material's name, for the weak-key error.
|
|
50
|
+
* @param keyMaterial - At least {@link MIN_KEY_MATERIAL_LENGTH} characters.
|
|
51
|
+
* @param info - The HKDF context string; decryption must pass the same one.
|
|
52
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
53
|
+
* @returns A base64url token of `salt || iv || ciphertext+tag`.
|
|
54
|
+
* @throws WeakKeyMaterialError when `keyMaterial` is too short.
|
|
55
|
+
*/
|
|
11
56
|
export declare const encryptWithKeyMaterial: (name: string, keyMaterial: string, info: string, value: unknown) => Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Reverses {@link encryptWithKeyMaterial}.
|
|
59
|
+
*
|
|
60
|
+
* @param name - The key material's name, for the weak-key error.
|
|
61
|
+
* @param keyMaterial - The material the token was encrypted under.
|
|
62
|
+
* @param info - The same HKDF context string used to encrypt.
|
|
63
|
+
* @param token - The base64url token to decrypt.
|
|
64
|
+
* @returns The parsed value, cast to `T` without validation.
|
|
65
|
+
* @throws WeakKeyMaterialError when `keyMaterial` is too short; Error on a
|
|
66
|
+
* truncated token; the WebCrypto `OperationError` when the key, `info` or
|
|
67
|
+
* token is wrong.
|
|
68
|
+
*/
|
|
12
69
|
export declare const decryptWithKeyMaterial: <T>(name: string, keyMaterial: string, info: string, token: string) => Promise<T>;
|
|
70
|
+
/** UTF-8 encodes a string and returns it as unpadded base64url. An encoding, not encryption. */
|
|
13
71
|
export declare const encodeBase64UrlText: (value: string) => string;
|
|
72
|
+
/** Decodes unpadded (or padded) base64url back to a UTF-8 string. */
|
|
14
73
|
export declare const decodeBase64UrlText: (value: string) => string;
|
|
15
74
|
/**
|
|
16
75
|
* HMAC-SHA256 over `payload` under a key expanded from high-entropy key
|
|
@@ -20,19 +79,48 @@ export declare const decodeBase64UrlText: (value: string) => string;
|
|
|
20
79
|
export declare const signWithKeyMaterial: (name: string, keyMaterial: string, info: string, payload: string) => Promise<string>;
|
|
21
80
|
/** False — never throws — for a malformed, truncated or mismatched signature. */
|
|
22
81
|
export declare const verifyWithKeyMaterial: (name: string, keyMaterial: string, info: string, payload: string, signature: string) => Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Generates a random 256-bit data-encryption key for envelope encryption.
|
|
84
|
+
*
|
|
85
|
+
* @returns The raw key as base64url. It is plaintext key material: wrap it with
|
|
86
|
+
* {@link wrapDEK} before storing it.
|
|
87
|
+
*/
|
|
23
88
|
export declare const generateDEK: () => Promise<string>;
|
|
24
89
|
/**
|
|
25
90
|
* One salt per (deployment, key version), stored beside the wrapped DEKs.
|
|
26
91
|
* See knowledge/crypto.md.
|
|
27
92
|
*/
|
|
28
93
|
export declare const generateKEKSalt: () => string;
|
|
94
|
+
/**
|
|
95
|
+
* Derives the AES-256-GCM key-encryption key from a passphrase and a salt from
|
|
96
|
+
* {@link generateKEKSalt}, by PBKDF2-SHA256 (600,000 iterations). The key is
|
|
97
|
+
* non-extractable.
|
|
98
|
+
*
|
|
99
|
+
* @param passphrase - The deployment's master passphrase.
|
|
100
|
+
* @param salt - The base64url salt stored beside the wrapped DEKs.
|
|
101
|
+
*/
|
|
29
102
|
export declare const deriveKEK: (passphrase: string, salt: string) => Promise<CryptoKey>;
|
|
103
|
+
/** Encrypts a plaintext DEK under the KEK (AES-GCM, random IV) so it can be stored. */
|
|
30
104
|
export declare const wrapDEK: (kek: CryptoKey, plaintextDEK: string) => Promise<WrappedValue>;
|
|
105
|
+
/**
|
|
106
|
+
* Decrypts a DEK wrapped by {@link wrapDEK}.
|
|
107
|
+
*
|
|
108
|
+
* @throws Error on a truncated token; the WebCrypto `OperationError` when the KEK is wrong.
|
|
109
|
+
*/
|
|
31
110
|
export declare const unwrapDEK: (kek: CryptoKey, wrappedDEK: string) => Promise<string>;
|
|
111
|
+
/** The two values {@link envelopeEncrypt} returns; both are needed to decrypt and both are safe to store. */
|
|
32
112
|
export interface EnvelopeEncryptResult {
|
|
33
113
|
ciphertext: WrappedValue;
|
|
34
114
|
wrappedDEK: WrappedValue;
|
|
35
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Envelope-encrypts a value: a fresh DEK encrypts the value, and the KEK encrypts
|
|
118
|
+
* the DEK. Rotating the KEK then only needs {@link envelopeRewrap} on each
|
|
119
|
+
* wrapped DEK, not re-encryption of the data.
|
|
120
|
+
*
|
|
121
|
+
* @param kek - The key-encryption key from {@link deriveKEK}.
|
|
122
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
123
|
+
*/
|
|
36
124
|
export declare const envelopeEncrypt: (kek: CryptoKey, value: unknown) => Promise<EnvelopeEncryptResult>;
|
|
37
125
|
/**
|
|
38
126
|
* Note the inputs are plain `string`, not `WrappedValue`.
|
|
@@ -45,4 +133,9 @@ export declare const envelopeEncrypt: (kek: CryptoKey, value: unknown) => Promis
|
|
|
45
133
|
* wire, which is exactly where casts are least reviewable.
|
|
46
134
|
*/
|
|
47
135
|
export declare const envelopeDecrypt: <T>(kek: CryptoKey, ciphertext: string, wrappedDEK: string) => Promise<T>;
|
|
136
|
+
/**
|
|
137
|
+
* Re-wraps a DEK under a new KEK for key rotation. The data ciphertext is unchanged.
|
|
138
|
+
*
|
|
139
|
+
* @throws The WebCrypto `OperationError` when `oldKEK` did not wrap this DEK.
|
|
140
|
+
*/
|
|
48
141
|
export declare const envelopeRewrap: (oldKEK: CryptoKey, newKEK: CryptoKey, wrappedDEK: string) => Promise<WrappedValue>;
|
package/dist/crypto-utils.js
CHANGED
|
@@ -55,6 +55,18 @@ const deriveKey = async (secret, salt) => {
|
|
|
55
55
|
hash: 'SHA-256',
|
|
56
56
|
}, material, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
|
|
57
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Encrypts a JSON-serialisable value with AES-256-GCM under a key derived from
|
|
60
|
+
* `secret` by PBKDF2-SHA256 (600,000 iterations, fresh random 16-byte salt).
|
|
61
|
+
*
|
|
62
|
+
* Meant for low-entropy secrets such as passphrases; for high-entropy key material
|
|
63
|
+
* use {@link encryptWithKeyMaterial}, which skips the deliberately slow KDF.
|
|
64
|
+
*
|
|
65
|
+
* @param secret - The passphrase the key is derived from.
|
|
66
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
67
|
+
* @returns A base64url token of `salt || iv || ciphertext+tag`.
|
|
68
|
+
* @throws Error when WebCrypto is not available in the runtime.
|
|
69
|
+
*/
|
|
58
70
|
export const encryptJSON = async (secret, value) => {
|
|
59
71
|
const crypto = globalThis.crypto;
|
|
60
72
|
if (!crypto?.getRandomValues) {
|
|
@@ -73,6 +85,16 @@ export const encryptJSON = async (secret, value) => {
|
|
|
73
85
|
out.set(cipherBytes, salt.length + iv.length);
|
|
74
86
|
return toBase64Url(out);
|
|
75
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Reverses {@link encryptJSON}: re-derives the key from `secret` and the salt in
|
|
90
|
+
* the token, then decrypts and parses the JSON.
|
|
91
|
+
*
|
|
92
|
+
* @param secret - The passphrase the token was encrypted with.
|
|
93
|
+
* @param token - The base64url token `encryptJSON` returned.
|
|
94
|
+
* @returns The parsed value, cast to `T` without validation.
|
|
95
|
+
* @throws Error on a truncated token; the WebCrypto `OperationError` when the
|
|
96
|
+
* secret is wrong or the token was tampered with (the GCM tag fails).
|
|
97
|
+
*/
|
|
76
98
|
export const decryptJSON = async (secret, token) => {
|
|
77
99
|
const subtle = getSubtle();
|
|
78
100
|
const data = fromBase64Url(token);
|
|
@@ -91,7 +113,16 @@ export const decryptJSON = async (secret, token) => {
|
|
|
91
113
|
* another purpose derives a different key. See knowledge/crypto.md.
|
|
92
114
|
*/
|
|
93
115
|
export const REMOTE_SESSION_INFO = 'pikku:remote-session';
|
|
116
|
+
/** Shortest key material, in characters, that the `*WithKeyMaterial` helpers accept. */
|
|
94
117
|
export const MIN_KEY_MATERIAL_LENGTH = 32;
|
|
118
|
+
/**
|
|
119
|
+
* Refuses key material shorter than {@link MIN_KEY_MATERIAL_LENGTH}. HKDF does no
|
|
120
|
+
* stretching, so a short secret would be brute-forceable.
|
|
121
|
+
*
|
|
122
|
+
* @param name - The secret's name, used in the error message (the value is never included).
|
|
123
|
+
* @param keyMaterial - The material to check.
|
|
124
|
+
* @throws WeakKeyMaterialError when the material is too short.
|
|
125
|
+
*/
|
|
95
126
|
export const assertStrongKeyMaterial = (name, keyMaterial) => {
|
|
96
127
|
if (keyMaterial.length < MIN_KEY_MATERIAL_LENGTH) {
|
|
97
128
|
throw new WeakKeyMaterialError(name, MIN_KEY_MATERIAL_LENGTH, keyMaterial.length);
|
|
@@ -107,6 +138,20 @@ const expandKeyMaterial = async (keyMaterial, info, salt) => {
|
|
|
107
138
|
info: encoder.encode(info),
|
|
108
139
|
}, material, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
|
|
109
140
|
};
|
|
141
|
+
/**
|
|
142
|
+
* Encrypts a JSON-serialisable value with AES-256-GCM under a key expanded from
|
|
143
|
+
* high-entropy key material by HKDF-SHA256, with a fresh random salt per call.
|
|
144
|
+
*
|
|
145
|
+
* `info` domain-separates the derived key, so the same deployment secret used for
|
|
146
|
+
* two purposes (e.g. {@link REMOTE_SESSION_INFO}) yields two unrelated keys.
|
|
147
|
+
*
|
|
148
|
+
* @param name - The key material's name, for the weak-key error.
|
|
149
|
+
* @param keyMaterial - At least {@link MIN_KEY_MATERIAL_LENGTH} characters.
|
|
150
|
+
* @param info - The HKDF context string; decryption must pass the same one.
|
|
151
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
152
|
+
* @returns A base64url token of `salt || iv || ciphertext+tag`.
|
|
153
|
+
* @throws WeakKeyMaterialError when `keyMaterial` is too short.
|
|
154
|
+
*/
|
|
110
155
|
export const encryptWithKeyMaterial = async (name, keyMaterial, info, value) => {
|
|
111
156
|
assertStrongKeyMaterial(name, keyMaterial);
|
|
112
157
|
const crypto = globalThis.crypto;
|
|
@@ -125,6 +170,18 @@ export const encryptWithKeyMaterial = async (name, keyMaterial, info, value) =>
|
|
|
125
170
|
out.set(cipherBytes, salt.length + iv.length);
|
|
126
171
|
return toBase64Url(out);
|
|
127
172
|
};
|
|
173
|
+
/**
|
|
174
|
+
* Reverses {@link encryptWithKeyMaterial}.
|
|
175
|
+
*
|
|
176
|
+
* @param name - The key material's name, for the weak-key error.
|
|
177
|
+
* @param keyMaterial - The material the token was encrypted under.
|
|
178
|
+
* @param info - The same HKDF context string used to encrypt.
|
|
179
|
+
* @param token - The base64url token to decrypt.
|
|
180
|
+
* @returns The parsed value, cast to `T` without validation.
|
|
181
|
+
* @throws WeakKeyMaterialError when `keyMaterial` is too short; Error on a
|
|
182
|
+
* truncated token; the WebCrypto `OperationError` when the key, `info` or
|
|
183
|
+
* token is wrong.
|
|
184
|
+
*/
|
|
128
185
|
export const decryptWithKeyMaterial = async (name, keyMaterial, info, token) => {
|
|
129
186
|
assertStrongKeyMaterial(name, keyMaterial);
|
|
130
187
|
const subtle = getSubtle();
|
|
@@ -139,7 +196,9 @@ export const decryptWithKeyMaterial = async (name, keyMaterial, info, token) =>
|
|
|
139
196
|
const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
|
|
140
197
|
return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
|
|
141
198
|
};
|
|
199
|
+
/** UTF-8 encodes a string and returns it as unpadded base64url. An encoding, not encryption. */
|
|
142
200
|
export const encodeBase64UrlText = (value) => toBase64Url(encoder.encode(value));
|
|
201
|
+
/** Decodes unpadded (or padded) base64url back to a UTF-8 string. */
|
|
143
202
|
export const decodeBase64UrlText = (value) => decoder.decode(fromBase64Url(value));
|
|
144
203
|
const expandSigningKeyMaterial = async (keyMaterial, info) => {
|
|
145
204
|
const subtle = getSubtle();
|
|
@@ -199,6 +258,12 @@ const decryptWithCryptoKey = async (key, token) => {
|
|
|
199
258
|
const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
|
|
200
259
|
return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
|
|
201
260
|
};
|
|
261
|
+
/**
|
|
262
|
+
* Generates a random 256-bit data-encryption key for envelope encryption.
|
|
263
|
+
*
|
|
264
|
+
* @returns The raw key as base64url. It is plaintext key material: wrap it with
|
|
265
|
+
* {@link wrapDEK} before storing it.
|
|
266
|
+
*/
|
|
202
267
|
export const generateDEK = async () => {
|
|
203
268
|
const raw = globalThis.crypto.getRandomValues(new Uint8Array(32));
|
|
204
269
|
return toBase64Url(raw);
|
|
@@ -214,6 +279,14 @@ export const generateKEKSalt = () => {
|
|
|
214
279
|
}
|
|
215
280
|
return toBase64Url(crypto.getRandomValues(new Uint8Array(SALT_BYTES)));
|
|
216
281
|
};
|
|
282
|
+
/**
|
|
283
|
+
* Derives the AES-256-GCM key-encryption key from a passphrase and a salt from
|
|
284
|
+
* {@link generateKEKSalt}, by PBKDF2-SHA256 (600,000 iterations). The key is
|
|
285
|
+
* non-extractable.
|
|
286
|
+
*
|
|
287
|
+
* @param passphrase - The deployment's master passphrase.
|
|
288
|
+
* @param salt - The base64url salt stored beside the wrapped DEKs.
|
|
289
|
+
*/
|
|
217
290
|
export const deriveKEK = async (passphrase, salt) => {
|
|
218
291
|
return deriveKey(passphrase, fromBase64Url(salt));
|
|
219
292
|
};
|
|
@@ -223,9 +296,15 @@ export const deriveKEK = async (passphrase, salt) => {
|
|
|
223
296
|
* once and audited once instead of at each call site.
|
|
224
297
|
*/
|
|
225
298
|
const asWrapped = (ciphertext) => ciphertext;
|
|
299
|
+
/** Encrypts a plaintext DEK under the KEK (AES-GCM, random IV) so it can be stored. */
|
|
226
300
|
export const wrapDEK = async (kek, plaintextDEK) => {
|
|
227
301
|
return asWrapped(await encryptWithCryptoKey(kek, plaintextDEK));
|
|
228
302
|
};
|
|
303
|
+
/**
|
|
304
|
+
* Decrypts a DEK wrapped by {@link wrapDEK}.
|
|
305
|
+
*
|
|
306
|
+
* @throws Error on a truncated token; the WebCrypto `OperationError` when the KEK is wrong.
|
|
307
|
+
*/
|
|
229
308
|
export const unwrapDEK = async (kek, wrappedDEK) => {
|
|
230
309
|
return decryptWithCryptoKey(kek, wrappedDEK);
|
|
231
310
|
};
|
|
@@ -235,6 +314,14 @@ const encryptWithDEK = async (dekBase64, value) => {
|
|
|
235
314
|
const decryptWithDEK = async (dekBase64, token) => {
|
|
236
315
|
return decryptWithCryptoKey(await importRawKey(fromBase64Url(dekBase64)), token);
|
|
237
316
|
};
|
|
317
|
+
/**
|
|
318
|
+
* Envelope-encrypts a value: a fresh DEK encrypts the value, and the KEK encrypts
|
|
319
|
+
* the DEK. Rotating the KEK then only needs {@link envelopeRewrap} on each
|
|
320
|
+
* wrapped DEK, not re-encryption of the data.
|
|
321
|
+
*
|
|
322
|
+
* @param kek - The key-encryption key from {@link deriveKEK}.
|
|
323
|
+
* @param value - Any value `JSON.stringify` accepts.
|
|
324
|
+
*/
|
|
238
325
|
export const envelopeEncrypt = async (kek, value) => {
|
|
239
326
|
const dek = await generateDEK();
|
|
240
327
|
const ciphertext = asWrapped(await encryptWithDEK(dek, value));
|
|
@@ -255,6 +342,11 @@ export const envelopeDecrypt = async (kek, ciphertext, wrappedDEK) => {
|
|
|
255
342
|
const dek = await unwrapDEK(kek, wrappedDEK);
|
|
256
343
|
return decryptWithDEK(dek, ciphertext);
|
|
257
344
|
};
|
|
345
|
+
/**
|
|
346
|
+
* Re-wraps a DEK under a new KEK for key rotation. The data ciphertext is unchanged.
|
|
347
|
+
*
|
|
348
|
+
* @throws The WebCrypto `OperationError` when `oldKEK` did not wrap this DEK.
|
|
349
|
+
*/
|
|
258
350
|
export const envelopeRewrap = async (oldKEK, newKEK, wrappedDEK) => {
|
|
259
351
|
const dek = await unwrapDEK(oldKEK, wrappedDEK);
|
|
260
352
|
return wrapDEK(newKEK, dek);
|
package/dist/dev/hot-reload.d.ts
CHANGED
|
@@ -4,10 +4,26 @@ interface PikkuDevReloaderOptions {
|
|
|
4
4
|
srcDirectories: string[];
|
|
5
5
|
logger: Logger;
|
|
6
6
|
}
|
|
7
|
+
/** Controls a running {@link pikkuDevReloader}. */
|
|
7
8
|
export interface PikkuDevReloaderHandle {
|
|
8
9
|
close: () => void;
|
|
9
10
|
/** Re-import every file changed since the last drain (post-codegen, once
|
|
10
11
|
* fresh meta is in state). */
|
|
11
12
|
reimportPending: () => Promise<void>;
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Watches the source directories and hot-swaps changed function exports into the
|
|
16
|
+
* running process, for `pikku dev`.
|
|
17
|
+
*
|
|
18
|
+
* Each changed `.ts` file (not tests, `.d.ts`, `.gen.ts` or hidden files) is
|
|
19
|
+
* re-imported after a 50ms debounce; every export that looks like a function
|
|
20
|
+
* config replaces the registered one, and the HTTP router and middleware,
|
|
21
|
+
* permission and channel-middleware caches are reset so re-run wirings take
|
|
22
|
+
* effect. A file that fails to import is logged and the old code is kept.
|
|
23
|
+
*
|
|
24
|
+
* Development only: it executes whatever is written to the watched directories.
|
|
25
|
+
*
|
|
26
|
+
* @param options - `srcDirectories` to watch and the `logger` reloads report to.
|
|
27
|
+
* @returns A handle to stop watching and to re-import files after codegen.
|
|
28
|
+
*/
|
|
13
29
|
export declare function pikkuDevReloader(options: PikkuDevReloaderOptions): Promise<PikkuDevReloaderHandle>;
|
package/dist/dev/hot-reload.js
CHANGED
|
@@ -3,7 +3,7 @@ import { basename, join, resolve, relative } from 'node:path';
|
|
|
3
3
|
import { pikkuState } from '../pikku-state.js';
|
|
4
4
|
import { clearMiddlewareCache } from '../middleware-runner.js';
|
|
5
5
|
import { clearPermissionsCache } from '../permissions.js';
|
|
6
|
-
import { clearChannelMiddlewareCache } from '../
|
|
6
|
+
import { clearChannelMiddlewareCache } from '../channel-middleware-runner.js';
|
|
7
7
|
import { httpRouter } from '../wirings/http/routers/http-router.js';
|
|
8
8
|
import { createModuleRunner, isTopLevelAwaitLimitation, } from './module-runner.js';
|
|
9
9
|
export { reloadGeneratedMeta, reconcileAddonRegistry } from './reload-meta.js';
|
|
@@ -35,6 +35,21 @@ const reloadFailureReason = (error) => {
|
|
|
35
35
|
}
|
|
36
36
|
return ` ${error.stack ?? error.message}`;
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Watches the source directories and hot-swaps changed function exports into the
|
|
40
|
+
* running process, for `pikku dev`.
|
|
41
|
+
*
|
|
42
|
+
* Each changed `.ts` file (not tests, `.d.ts`, `.gen.ts` or hidden files) is
|
|
43
|
+
* re-imported after a 50ms debounce; every export that looks like a function
|
|
44
|
+
* config replaces the registered one, and the HTTP router and middleware,
|
|
45
|
+
* permission and channel-middleware caches are reset so re-run wirings take
|
|
46
|
+
* effect. A file that fails to import is logged and the old code is kept.
|
|
47
|
+
*
|
|
48
|
+
* Development only: it executes whatever is written to the watched directories.
|
|
49
|
+
*
|
|
50
|
+
* @param options - `srcDirectories` to watch and the `logger` reloads report to.
|
|
51
|
+
* @returns A handle to stop watching and to re-import files after codegen.
|
|
52
|
+
*/
|
|
38
53
|
export async function pikkuDevReloader(options) {
|
|
39
54
|
const { srcDirectories, logger } = options;
|
|
40
55
|
const absSrcDirs = srcDirectories.map((d) => resolve(d));
|
|
@@ -7,9 +7,13 @@ let transformSync;
|
|
|
7
7
|
const loadTransform = async () => {
|
|
8
8
|
if (transformSync)
|
|
9
9
|
return transformSync;
|
|
10
|
-
// esbuild is
|
|
11
|
-
//
|
|
12
|
-
const esbuild = await import('esbuild')
|
|
10
|
+
// esbuild is an optional peer: only the dev-only `./dev` export needs it, so
|
|
11
|
+
// production installs never have to carry it.
|
|
12
|
+
const esbuild = await import('esbuild').catch((e) => {
|
|
13
|
+
if (e?.code !== 'ERR_MODULE_NOT_FOUND')
|
|
14
|
+
throw e;
|
|
15
|
+
throw new Error("@pikku/core/dev needs the optional peer dependency 'esbuild'. Install it in your project (npm install -D esbuild).", { cause: e });
|
|
16
|
+
});
|
|
13
17
|
transformSync = esbuild.transformSync;
|
|
14
18
|
return transformSync;
|
|
15
19
|
};
|
package/dist/dev/reload-meta.js
CHANGED
|
@@ -4,7 +4,7 @@ import { pikkuState } from '../pikku-state.js';
|
|
|
4
4
|
import { addSchema, compileAllSchemas } from '../schema.js';
|
|
5
5
|
import { clearMiddlewareCache } from '../middleware-runner.js';
|
|
6
6
|
import { clearPermissionsCache } from '../permissions.js';
|
|
7
|
-
import { clearChannelMiddlewareCache } from '../
|
|
7
|
+
import { clearChannelMiddlewareCache } from '../channel-middleware-runner.js';
|
|
8
8
|
import { httpRouter } from '../wirings/http/routers/http-router.js';
|
|
9
9
|
const readJson = async (logger, file) => {
|
|
10
10
|
let raw;
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for errors a function throws on purpose. Subclass it and register
|
|
3
|
+
* the subclass with {@link addError} to choose the status and message the
|
|
4
|
+
* caller gets; an unregistered error answers 500. `name` is set to the
|
|
5
|
+
* subclass's name, and {@link isExpectedError} treats every `PikkuError` as
|
|
6
|
+
* expected, so it is logged by message rather than with a stack trace.
|
|
7
|
+
* @group Error
|
|
8
|
+
*/
|
|
1
9
|
export declare class PikkuError extends Error {
|
|
2
10
|
constructor(message?: string);
|
|
3
11
|
}
|
|
@@ -10,6 +18,7 @@ export declare class PikkuError extends Error {
|
|
|
10
18
|
* @example snippet: isExpectedError
|
|
11
19
|
*/
|
|
12
20
|
export declare const isExpectedError: (error: unknown) => boolean;
|
|
21
|
+
/** What {@link addError} registers against an error class. */
|
|
13
22
|
export interface ErrorDetails {
|
|
14
23
|
/** The HTTP status this error answers with, instead of a 500. */
|
|
15
24
|
status: number;
|