@pikku/core 0.12.72 → 0.12.74
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/CHANGELOG.md +793 -0
- package/dist/crypto-utils.d.ts +30 -5
- package/dist/crypto-utils.js +146 -41
- package/dist/dev/hot-reload.js +11 -30
- package/dist/dev/module-runner.d.ts +3 -7
- package/dist/dev/module-runner.js +4 -10
- package/dist/dev/reload-meta.d.ts +8 -20
- package/dist/dev/reload-meta.js +9 -29
- package/dist/errors/error-handler.d.ts +5 -30
- package/dist/errors/error-handler.js +16 -32
- package/dist/errors/errors.d.ts +32 -151
- package/dist/errors/errors.js +55 -157
- package/dist/function/abort-scope.d.ts +47 -0
- package/dist/function/abort-scope.js +63 -0
- package/dist/function/function-runner.js +37 -32
- package/dist/function/functions.types.d.ts +44 -136
- package/dist/function/functions.types.js +0 -58
- package/dist/function/list.types.d.ts +12 -62
- package/dist/function/list.types.js +4 -25
- package/dist/handle-error.d.ts +0 -13
- package/dist/handle-error.js +0 -18
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -1
- package/dist/middleware/auth-apikey.d.ts +3 -18
- package/dist/middleware/auth-apikey.js +0 -17
- package/dist/middleware/auth-bearer.d.ts +6 -41
- package/dist/middleware/auth-bearer.js +3 -40
- package/dist/middleware/auth-cookie.d.ts +5 -27
- package/dist/middleware/auth-cookie.js +2 -26
- package/dist/middleware/cors.d.ts +7 -34
- package/dist/middleware/cors.js +7 -34
- package/dist/middleware/remote-auth.d.ts +3 -1
- package/dist/middleware/remote-auth.js +3 -2
- package/dist/middleware/telemetry.d.ts +8 -33
- package/dist/middleware/telemetry.js +2 -31
- package/dist/middleware-runner.d.ts +4 -55
- package/dist/middleware-runner.js +5 -74
- package/dist/permissions.d.ts +3 -44
- package/dist/permissions.js +19 -71
- package/dist/pikku-request.d.ts +0 -6
- package/dist/pikku-request.js +0 -6
- package/dist/pikku-state.d.ts +0 -26
- package/dist/pikku-state.js +2 -30
- package/dist/remote.d.ts +3 -5
- package/dist/remote.js +8 -7
- package/dist/schema.d.ts +5 -39
- package/dist/schema.js +5 -39
- package/dist/scopes.d.ts +4 -23
- package/dist/scopes.js +7 -48
- package/dist/services/ai-agent-runner-service.d.ts +20 -0
- package/dist/services/ai-embedding-service.d.ts +2 -25
- package/dist/services/audit-service.js +1 -2
- package/dist/services/content-service.d.ts +1 -46
- package/dist/services/credential-service.d.ts +3 -40
- package/dist/services/deployment-service.d.ts +3 -9
- package/dist/services/gateway-service.d.ts +0 -15
- package/dist/services/http-personas.d.ts +80 -0
- package/dist/services/http-personas.js +233 -0
- package/dist/services/in-memory-queue-service.d.ts +0 -14
- package/dist/services/in-memory-queue-service.js +1 -15
- package/dist/services/in-memory-trigger-service.d.ts +0 -18
- package/dist/services/in-memory-trigger-service.js +1 -18
- package/dist/services/in-memory-workflow-service.d.ts +0 -16
- package/dist/services/in-memory-workflow-service.js +4 -33
- package/dist/services/index.d.ts +5 -6
- package/dist/services/index.js +2 -5
- package/dist/services/istanbul-coverage-service.d.ts +1 -5
- package/dist/services/istanbul-coverage-service.js +2 -8
- package/dist/services/jwt-service.d.ts +1 -16
- package/dist/services/local-content.d.ts +13 -2
- package/dist/services/local-content.js +40 -13
- package/dist/services/local-gateway-service.d.ts +0 -16
- package/dist/services/local-gateway-service.js +2 -17
- package/dist/services/local-secrets.d.ts +0 -4
- package/dist/services/local-secrets.js +0 -4
- package/dist/services/logger-console.d.ts +3 -7
- package/dist/services/logger-console.js +3 -7
- package/dist/services/logger.d.ts +2 -37
- package/dist/services/meta-service.d.ts +23 -26
- package/dist/services/meta-service.js +22 -36
- package/dist/services/personas-service.d.ts +134 -0
- package/dist/services/personas-service.js +40 -0
- package/dist/services/pikku-user-id.js +0 -4
- package/dist/services/queue-webhook-service.d.ts +2 -36
- package/dist/services/queue-webhook-service.js +9 -41
- package/dist/services/scheduler-service.d.ts +1 -50
- package/dist/services/scheduler-service.js +0 -10
- package/dist/services/schema-service.d.ts +1 -24
- package/dist/services/scope-service.d.ts +49 -34
- package/dist/services/scoped-secret-service.d.ts +0 -4
- package/dist/services/scoped-secret-service.js +0 -4
- package/dist/services/secret-host-binding.d.ts +8 -0
- package/dist/services/secret-host-binding.js +36 -0
- package/dist/services/secret-service.d.ts +5 -33
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +21 -0
- package/dist/services/stub-tracker.d.ts +7 -18
- package/dist/services/stub-tracker.js +8 -18
- package/dist/services/system-role-guard.d.ts +33 -0
- package/dist/services/system-role-guard.js +38 -0
- package/dist/services/trigger-service.d.ts +0 -12
- package/dist/services/typed-secret-service.d.ts +0 -7
- package/dist/services/typed-secret-service.js +1 -7
- package/dist/services/v8-coverage-service.d.ts +2 -3
- package/dist/services/v8-coverage-service.js +1 -2
- package/dist/services/variables-service.d.ts +1 -8
- package/dist/services/webhook-service.d.ts +19 -63
- package/dist/services/webhook-service.js +6 -20
- package/dist/services/workflow-service.d.ts +3 -15
- package/dist/testing/service-tests.js +0 -17
- package/dist/time-utils.d.ts +0 -16
- package/dist/time-utils.js +1 -19
- package/dist/types/core.types.d.ts +99 -219
- package/dist/types/core.types.js +0 -42
- package/dist/types/state.types.d.ts +4 -9
- package/dist/utils/hmac.d.ts +4 -10
- package/dist/utils/hmac.js +4 -10
- package/dist/utils/safe-fetch.d.ts +7 -35
- package/dist/utils/safe-fetch.js +13 -53
- package/dist/utils.d.ts +1 -6
- package/dist/utils.js +6 -15
- package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
- package/dist/wirings/actor-flow/index.d.ts +0 -9
- package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
- package/dist/wirings/actor-flow/run-conversation.js +14 -7
- package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
- package/dist/wirings/ai-agent/ai-agent-agui.js +34 -12
- package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
- package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
- package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
- package/dist/wirings/ai-agent/ai-agent-prepare.js +58 -131
- package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
- package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
- package/dist/wirings/ai-agent/ai-agent-runner.js +49 -20
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
- package/dist/wirings/ai-agent/ai-agent-stream.js +153 -63
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +84 -4
- package/dist/wirings/ai-agent/index.d.ts +6 -4
- package/dist/wirings/ai-agent/index.js +5 -4
- package/dist/wirings/ai-agent/voice-input.d.ts +39 -1
- package/dist/wirings/ai-agent/voice-input.js +46 -3
- package/dist/wirings/ai-agent/voice-output.d.ts +54 -1
- package/dist/wirings/ai-agent/voice-output.js +153 -50
- package/dist/wirings/channel/channel-common.d.ts +7 -20
- package/dist/wirings/channel/channel-common.js +7 -21
- package/dist/wirings/channel/channel-handler.js +25 -6
- package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
- package/dist/wirings/channel/channel-host-rpc.js +38 -0
- package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
- package/dist/wirings/channel/channel-middleware-runner.js +0 -12
- package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
- package/dist/wirings/channel/channel-rpc-registry.js +89 -0
- package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
- package/dist/wirings/channel/channel-rpc-responder.js +71 -0
- package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
- package/dist/wirings/channel/channel-rpc-service.js +106 -0
- package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
- package/dist/wirings/channel/channel-rpc-validators.js +30 -0
- package/dist/wirings/channel/channel-rpc.d.ts +5 -0
- package/dist/wirings/channel/channel-rpc.js +5 -0
- package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
- package/dist/wirings/channel/channel-rpc.types.js +50 -0
- package/dist/wirings/channel/channel-runner.d.ts +0 -4
- package/dist/wirings/channel/channel-runner.js +0 -14
- package/dist/wirings/channel/channel-store.d.ts +0 -10
- package/dist/wirings/channel/channel.types.d.ts +12 -1
- package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
- package/dist/wirings/channel/define-channel-routes.js +0 -20
- package/dist/wirings/channel/eventhub-service.d.ts +0 -18
- package/dist/wirings/channel/index.d.ts +4 -1
- package/dist/wirings/channel/index.js +2 -0
- package/dist/wirings/channel/local/local-channel-runner.js +3 -1
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
- package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
- package/dist/wirings/channel/log-channels.d.ts +0 -4
- package/dist/wirings/channel/log-channels.js +0 -4
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
- package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
- package/dist/wirings/cli/channel/cli-approval.js +81 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
- package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
- package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
- package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +20 -0
- package/dist/wirings/cli/channel/cli-raw-client-runner.js +121 -0
- package/dist/wirings/cli/channel/index.d.ts +4 -0
- package/dist/wirings/cli/channel/index.js +2 -0
- package/dist/wirings/cli/cli-runner.d.ts +20 -20
- package/dist/wirings/cli/cli-runner.js +28 -89
- package/dist/wirings/cli/cli.types.d.ts +14 -3
- package/dist/wirings/cli/command-parser.d.ts +1 -10
- package/dist/wirings/cli/command-parser.js +10 -87
- package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
- package/dist/wirings/cli/define-cli-commands.js +1 -17
- package/dist/wirings/credential/credential.types.d.ts +0 -12
- package/dist/wirings/credential/define-credential.d.ts +48 -0
- package/dist/wirings/credential/define-credential.js +47 -0
- package/dist/wirings/credential/index.d.ts +1 -1
- package/dist/wirings/credential/index.js +1 -1
- package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
- package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
- package/dist/wirings/gateway/gateway-runner.js +8 -105
- package/dist/wirings/gateway/gateway.types.d.ts +7 -80
- package/dist/wirings/http/http-routes.d.ts +0 -63
- package/dist/wirings/http/http-routes.js +0 -63
- package/dist/wirings/http/http-runner.d.ts +0 -99
- package/dist/wirings/http/http-runner.js +9 -165
- package/dist/wirings/http/http.types.d.ts +14 -55
- package/dist/wirings/http/log-http-routes.d.ts +0 -4
- package/dist/wirings/http/log-http-routes.js +0 -4
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
- package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
- package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
- package/dist/wirings/http/routers/path-to-regex.js +2 -13
- package/dist/wirings/http/web-request.d.ts +0 -8
- package/dist/wirings/http/web-request.js +25 -17
- package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
- package/dist/wirings/mcp/mcp-runner.js +1 -14
- package/dist/wirings/mcp/mcp.types.d.ts +2 -35
- package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
- package/dist/wirings/oauth2/oauth2.types.js +0 -3
- package/dist/wirings/persona/define-personas.d.ts +28 -0
- package/dist/wirings/persona/define-personas.js +27 -0
- package/dist/wirings/persona/index.d.ts +21 -0
- package/dist/wirings/persona/index.js +17 -0
- package/dist/wirings/persona/persona-email.d.ts +37 -0
- package/dist/wirings/persona/persona-email.js +69 -0
- package/dist/wirings/persona/persona-environments.d.ts +45 -0
- package/dist/wirings/persona/persona-environments.js +81 -0
- package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
- package/dist/wirings/persona/persona-mailbox.js +53 -0
- package/dist/wirings/persona/persona.types.d.ts +125 -0
- package/dist/wirings/persona/persona.types.js +1 -0
- package/dist/wirings/persona/validate-personas.d.ts +53 -0
- package/dist/wirings/persona/validate-personas.js +94 -0
- package/dist/wirings/queue/index.d.ts +3 -0
- package/dist/wirings/queue/index.js +2 -3
- package/dist/wirings/queue/queue-identity.d.ts +28 -0
- package/dist/wirings/queue/queue-identity.js +102 -0
- package/dist/wirings/queue/queue-runner.d.ts +0 -19
- package/dist/wirings/queue/queue-runner.js +9 -30
- package/dist/wirings/queue/queue.types.d.ts +18 -89
- package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
- package/dist/wirings/queue/register-queue-helper.js +0 -11
- package/dist/wirings/queue/signed-queue-service.d.ts +16 -0
- package/dist/wirings/queue/signed-queue-service.js +42 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
- package/dist/wirings/queue/validate-worker-config.js +0 -14
- package/dist/wirings/role/define-system-role.d.ts +32 -0
- package/dist/wirings/role/define-system-role.js +31 -0
- package/dist/wirings/role/index.d.ts +3 -0
- package/dist/wirings/role/index.js +2 -0
- package/dist/wirings/role/role.types.d.ts +43 -0
- package/dist/wirings/role/role.types.js +1 -0
- package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
- package/dist/wirings/role/validate-role-definitions.js +71 -0
- package/dist/wirings/rpc/addon-runner.d.ts +0 -19
- package/dist/wirings/rpc/addon-runner.js +0 -51
- package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -12
- package/dist/wirings/rpc/remote-addon-auth.js +1 -9
- package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
- package/dist/wirings/rpc/rpc-runner.js +88 -105
- package/dist/wirings/rpc/rpc-types.d.ts +7 -6
- package/dist/wirings/rpc/wire-addon.d.ts +25 -0
- package/dist/wirings/rpc/wire-addon.js +62 -0
- package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
- package/dist/wirings/rpc/wire-remote-addon.js +0 -8
- package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
- package/dist/wirings/scheduler/log-schedulers.js +0 -4
- package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
- package/dist/wirings/scheduler/scheduler-runner.js +0 -1
- package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
- package/dist/wirings/scope/define-scope.d.ts +32 -0
- package/dist/wirings/scope/define-scope.js +31 -0
- package/dist/wirings/scope/index.d.ts +1 -1
- package/dist/wirings/scope/index.js +1 -1
- package/dist/wirings/scope/scope.types.d.ts +7 -9
- package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
- package/dist/wirings/scope/validate-scope-definitions.js +3 -21
- package/dist/wirings/secret/index.d.ts +1 -1
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +19 -15
- package/dist/wirings/secret/secret.types.js +1 -1
- package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
- package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
- package/dist/wirings/trigger/trigger-runner.js +1 -24
- package/dist/wirings/trigger/trigger.types.d.ts +1 -82
- package/dist/wirings/trigger/trigger.types.js +0 -34
- package/dist/wirings/variable/index.d.ts +1 -1
- package/dist/wirings/variable/index.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
- package/dist/wirings/variable/variable.types.d.ts +1 -13
- package/dist/wirings/variable/variable.types.js +1 -1
- package/dist/wirings/virtual-user/index.d.ts +27 -0
- package/dist/wirings/virtual-user/index.js +8 -0
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
- package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
- package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
- package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
- package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
- package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
- package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
- package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
- package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
- package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
- package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
- package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
- package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
- package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
- package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
- package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
- package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +5 -5
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
- package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
- package/dist/wirings/workflow/feature.d.ts +0 -19
- package/dist/wirings/workflow/feature.js +0 -19
- package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
- package/dist/wirings/workflow/graph/graph-node.js +0 -34
- package/dist/wirings/workflow/graph/graph-runner.js +6 -41
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
- package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
- package/dist/wirings/workflow/index.d.ts +5 -7
- package/dist/wirings/workflow/index.js +3 -17
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
- package/dist/wirings/workflow/pikku-scenario-service.js +204 -42
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
- package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
- package/dist/wirings/workflow/run-timeline.d.ts +0 -47
- package/dist/wirings/workflow/run-timeline.js +0 -22
- package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
- package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
- package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
- package/dist/wirings/workflow/scenario-poll.js +0 -12
- package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
- package/dist/wirings/workflow/scenario-prose.js +0 -18
- package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
- package/dist/wirings/workflow/scenario-step-guards.js +1 -14
- package/dist/wirings/workflow/scenario-step.types.d.ts +72 -6
- package/dist/wirings/workflow/scenario-step.types.js +5 -1
- package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
- package/dist/wirings/workflow/scenario-surface.js +56 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
- package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
- package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
- package/dist/wirings/workflow/workflow.types.d.ts +0 -197
- package/knowledge/decisions/index.md +19 -0
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
- package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
- package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
- package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
- package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
- package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
- package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
- package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
- package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
- package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
- package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
- package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
- package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
- package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
- package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
- package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
- package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +34 -0
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
- package/knowledge/decisions/internals/index.md +113 -0
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
- package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
- package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
- package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
- package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
- package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
- package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
- package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
- package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
- package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
- package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
- package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
- package/knowledge/decisions/security/index.md +55 -0
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
- package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
- package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
- package/knowledge/index.md +24 -0
- package/knowledge/questions/index.md +15 -0
- package/package.json +4 -1
- package/run-tests.sh +0 -0
- package/src/crypto-utils.test.ts +460 -19
- package/src/crypto-utils.ts +283 -55
- package/src/data-classification.ts +1 -7
- package/src/dev/hot-reload.test.ts +0 -4
- package/src/dev/hot-reload.ts +11 -30
- package/src/dev/module-runner.ts +7 -32
- package/src/dev/reload-meta.ts +9 -29
- package/src/errors/error-handler.ts +20 -35
- package/src/errors/error.test.ts +30 -1
- package/src/errors/errors.ts +73 -157
- package/src/function/abort-scope.test.ts +97 -0
- package/src/function/abort-scope.ts +80 -0
- package/src/function/function-runner.test.ts +0 -7
- package/src/function/function-runner.ts +62 -32
- package/src/function/functions.types.ts +56 -136
- package/src/function/list.types.test.ts +3 -25
- package/src/function/list.types.ts +12 -62
- package/src/handle-error.ts +0 -18
- package/src/index.ts +60 -1
- package/src/middleware/auth-apikey.test.ts +0 -1
- package/src/middleware/auth-apikey.ts +0 -17
- package/src/middleware/auth-bearer.test.ts +0 -3
- package/src/middleware/auth-bearer.ts +3 -40
- package/src/middleware/auth-cookie.test.ts +0 -6
- package/src/middleware/auth-cookie.ts +2 -26
- package/src/middleware/cors.test.ts +34 -0
- package/src/middleware/cors.ts +12 -33
- package/src/middleware/remote-auth.test.ts +24 -9
- package/src/middleware/remote-auth.ts +10 -2
- package/src/middleware/telemetry.ts +2 -31
- package/src/middleware-runner.test.ts +0 -2
- package/src/middleware-runner.ts +5 -74
- package/src/permissions.test.ts +30 -0
- package/src/permissions.ts +24 -74
- package/src/pikku-request.ts +0 -6
- package/src/pikku-state.ts +2 -30
- package/src/production-barrels-stay-lean.test.ts +110 -0
- package/src/remote.test.ts +172 -0
- package/src/remote.ts +17 -7
- package/src/schema.ts +5 -39
- package/src/scopes.ts +7 -48
- package/src/services/ai-agent-runner-service.ts +20 -0
- package/src/services/ai-embedding-service.ts +3 -25
- package/src/services/audit-service.ts +1 -2
- package/src/services/content-service.ts +1 -46
- package/src/services/credential-service.ts +3 -40
- package/src/services/credential-wire-service.test.ts +0 -2
- package/src/services/deployment-service.ts +3 -9
- package/src/services/gateway-service.ts +0 -15
- package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
- package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
- package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
- package/src/services/in-memory-queue-service.ts +1 -15
- package/src/services/in-memory-trigger-service.ts +1 -18
- package/src/services/in-memory-workflow-service.test.ts +0 -13
- package/src/services/in-memory-workflow-service.ts +4 -38
- package/src/services/index.ts +20 -15
- package/src/services/istanbul-coverage-service.ts +2 -8
- package/src/services/jwt-service.ts +1 -16
- package/src/services/local-content.test.ts +159 -27
- package/src/services/local-content.ts +55 -23
- package/src/services/local-gateway-service.ts +2 -17
- package/src/services/local-secrets.ts +0 -4
- package/src/services/logger-console.test.ts +0 -1
- package/src/services/logger-console.ts +3 -7
- package/src/services/logger.ts +2 -37
- package/src/services/meta-service.test.ts +1 -5
- package/src/services/meta-service.ts +41 -61
- package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
- package/src/services/pikku-user-id.ts +0 -4
- package/src/services/queue-webhook-service.ts +9 -41
- package/src/services/scheduler-service.ts +1 -50
- package/src/services/schema-service.ts +1 -24
- package/src/services/scope-service.ts +50 -34
- package/src/services/scoped-secret-service.ts +0 -4
- package/src/services/secret-host-binding.test.ts +138 -0
- package/src/services/secret-host-binding.ts +51 -0
- package/src/services/secret-service.ts +5 -33
- package/src/services/secretless.test.ts +54 -0
- package/src/services/secretless.ts +29 -0
- package/src/services/stub-tracker.ts +8 -18
- package/src/services/system-role-guard.test.ts +93 -0
- package/src/services/system-role-guard.ts +71 -0
- package/src/services/trigger-service.ts +0 -12
- package/src/services/typed-secret-service.ts +1 -7
- package/src/services/v8-coverage-service.ts +3 -6
- package/src/services/variables-service.ts +1 -8
- package/src/services/webhook-service.ts +19 -63
- package/src/services/workflow-service.ts +3 -20
- package/src/testing/service-tests.ts +0 -26
- package/src/time-utils.ts +1 -19
- package/src/types/core.types.ts +116 -229
- package/src/types/state.types.ts +7 -9
- package/src/utils/hmac.ts +4 -10
- package/src/utils/safe-fetch.ts +13 -54
- package/src/utils.test.ts +11 -2
- package/src/utils.ts +6 -15
- package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
- package/src/wirings/actor-flow/index.ts +0 -9
- package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
- package/src/wirings/actor-flow/run-conversation.ts +19 -12
- package/src/wirings/ai-agent/ai-agent-agui.test.ts +75 -10
- package/src/wirings/ai-agent/ai-agent-agui.ts +36 -17
- package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
- package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
- package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
- package/src/wirings/ai-agent/ai-agent-prepare.ts +82 -138
- package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
- package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
- package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
- package/src/wirings/ai-agent/ai-agent-runner.ts +67 -33
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
- package/src/wirings/ai-agent/ai-agent-stream.ts +192 -75
- package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +85 -4
- package/src/wirings/ai-agent/index.ts +35 -3
- package/src/wirings/ai-agent/voice-input.test.ts +72 -7
- package/src/wirings/ai-agent/voice-input.ts +48 -3
- package/src/wirings/ai-agent/voice-output.test.ts +422 -0
- package/src/wirings/ai-agent/voice-output.ts +216 -56
- package/src/wirings/channel/channel-common.ts +15 -20
- package/src/wirings/channel/channel-handler.test.ts +50 -0
- package/src/wirings/channel/channel-handler.ts +32 -11
- package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
- package/src/wirings/channel/channel-host-rpc.ts +69 -0
- package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
- package/src/wirings/channel/channel-middleware-runner.ts +0 -12
- package/src/wirings/channel/channel-rpc-registry.ts +116 -0
- package/src/wirings/channel/channel-rpc-responder.ts +117 -0
- package/src/wirings/channel/channel-rpc-service.ts +146 -0
- package/src/wirings/channel/channel-rpc-validators.ts +65 -0
- package/src/wirings/channel/channel-rpc.test.ts +820 -0
- package/src/wirings/channel/channel-rpc.ts +5 -0
- package/src/wirings/channel/channel-rpc.types.ts +150 -0
- package/src/wirings/channel/channel-runner.ts +0 -14
- package/src/wirings/channel/channel-store.ts +0 -10
- package/src/wirings/channel/channel.types.ts +19 -8
- package/src/wirings/channel/define-channel-routes.ts +0 -20
- package/src/wirings/channel/eventhub-service.ts +0 -18
- package/src/wirings/channel/index.ts +35 -0
- package/src/wirings/channel/local/local-channel-handler.ts +3 -1
- package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
- package/src/wirings/channel/local/local-channel-runner.ts +3 -1
- package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
- package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
- package/src/wirings/channel/log-channels.ts +0 -4
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
- package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
- package/src/wirings/cli/channel/cli-approval.ts +135 -0
- package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
- package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +155 -0
- package/src/wirings/cli/channel/index.ts +9 -0
- package/src/wirings/cli/cli-runner.test.ts +0 -1
- package/src/wirings/cli/cli-runner.ts +46 -88
- package/src/wirings/cli/cli.types.ts +14 -3
- package/src/wirings/cli/command-parser.test.ts +0 -4
- package/src/wirings/cli/command-parser.ts +11 -91
- package/src/wirings/cli/define-cli-commands.ts +1 -17
- package/src/wirings/credential/credential.types.ts +0 -12
- package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
- package/src/wirings/credential/index.ts +1 -1
- package/src/wirings/credential/validate-credential-definitions.ts +2 -4
- package/src/wirings/gateway/gateway-runner.test.ts +1 -21
- package/src/wirings/gateway/gateway-runner.ts +8 -110
- package/src/wirings/gateway/gateway.types.ts +7 -80
- package/src/wirings/http/http-routes.test.ts +0 -3
- package/src/wirings/http/http-routes.ts +0 -86
- package/src/wirings/http/http-runner.test.ts +0 -1
- package/src/wirings/http/http-runner.ts +8 -167
- package/src/wirings/http/http.types.ts +15 -62
- package/src/wirings/http/log-http-routes.ts +0 -4
- package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
- package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
- package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
- package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
- package/src/wirings/http/routers/path-to-regex.ts +2 -13
- package/src/wirings/http/web-request.test.ts +33 -2
- package/src/wirings/http/web-request.ts +30 -17
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
- package/src/wirings/mcp/mcp-runner.ts +2 -17
- package/src/wirings/mcp/mcp.types.ts +7 -42
- package/src/wirings/oauth2/oauth2.types.ts +0 -30
- package/src/wirings/persona/define-personas.ts +29 -0
- package/src/wirings/persona/index.ts +62 -0
- package/src/wirings/persona/persona-email.ts +87 -0
- package/src/wirings/persona/persona-environments.test.ts +183 -0
- package/src/wirings/persona/persona-environments.ts +138 -0
- package/src/wirings/persona/persona-mailbox.ts +156 -0
- package/src/wirings/persona/persona.test.ts +220 -0
- package/src/wirings/persona/persona.types.ts +131 -0
- package/src/wirings/persona/validate-personas.ts +133 -0
- package/src/wirings/queue/index.ts +13 -3
- package/src/wirings/queue/queue-identity.test.ts +453 -0
- package/src/wirings/queue/queue-identity.ts +173 -0
- package/src/wirings/queue/queue-runner.ts +12 -31
- package/src/wirings/queue/queue.types.ts +19 -89
- package/src/wirings/queue/register-queue-helper.ts +0 -14
- package/src/wirings/queue/signed-queue-service.ts +59 -0
- package/src/wirings/queue/validate-worker-config.ts +2 -28
- package/src/wirings/role/define-system-role.ts +33 -0
- package/src/wirings/role/index.ts +13 -0
- package/src/wirings/role/role.test.ts +104 -0
- package/src/wirings/role/role.types.ts +47 -0
- package/src/wirings/role/validate-role-definitions.ts +93 -0
- package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
- package/src/wirings/rpc/addon-runner.ts +0 -56
- package/src/wirings/rpc/addon-scopes.test.ts +225 -0
- package/src/wirings/rpc/remote-addon-auth.ts +1 -13
- package/src/wirings/rpc/rpc-runner.test.ts +186 -2
- package/src/wirings/rpc/rpc-runner.ts +145 -127
- package/src/wirings/rpc/rpc-types.ts +11 -6
- package/src/wirings/rpc/wire-addon.test.ts +43 -1
- package/src/wirings/rpc/wire-addon.ts +99 -0
- package/src/wirings/rpc/wire-remote-addon.ts +9 -29
- package/src/wirings/scheduler/log-schedulers.ts +0 -4
- package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
- package/src/wirings/scheduler/scheduler-runner.ts +0 -2
- package/src/wirings/scheduler/scheduler.types.ts +1 -14
- package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
- package/src/wirings/scope/index.ts +1 -1
- package/src/wirings/scope/scope.test.ts +1 -2
- package/src/wirings/scope/scope.types.ts +7 -9
- package/src/wirings/scope/validate-scope-definitions.ts +3 -21
- package/src/wirings/secret/index.ts +1 -1
- package/src/wirings/secret/secret.types.ts +19 -15
- package/src/wirings/secret/validate-secret-definitions.ts +2 -4
- package/src/wirings/trigger/trigger-runner.ts +1 -27
- package/src/wirings/trigger/trigger.types.ts +1 -82
- package/src/wirings/variable/index.ts +1 -1
- package/src/wirings/variable/validate-variable-definitions.ts +2 -4
- package/src/wirings/variable/variable.types.ts +1 -13
- package/src/wirings/virtual-user/index.ts +76 -0
- package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
- package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
- package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
- package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
- package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
- package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
- package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
- package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
- package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
- package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
- package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
- package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +5 -4
- package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
- package/src/wirings/workflow/feature.ts +0 -19
- package/src/wirings/workflow/graph/graph-node.ts +0 -136
- package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
- package/src/wirings/workflow/graph/graph-runner.ts +6 -41
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
- package/src/wirings/workflow/index.ts +10 -44
- package/src/wirings/workflow/pikku-scenario-service.ts +235 -52
- package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
- package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
- package/src/wirings/workflow/run-timeline.test.ts +7 -19
- package/src/wirings/workflow/run-timeline.ts +0 -56
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
- package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
- package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
- package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
- package/src/wirings/workflow/scenario-poll.test.ts +0 -2
- package/src/wirings/workflow/scenario-poll.ts +0 -15
- package/src/wirings/workflow/scenario-prose.ts +0 -28
- package/src/wirings/workflow/scenario-service.test.ts +2 -9
- package/src/wirings/workflow/scenario-step-guards.ts +1 -14
- package/src/wirings/workflow/scenario-step.test.ts +159 -14
- package/src/wirings/workflow/scenario-step.types.ts +82 -6
- package/src/wirings/workflow/scenario-surface.test.ts +145 -0
- package/src/wirings/workflow/scenario-surface.ts +71 -0
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
- package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
- package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
- package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
- package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
- package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
- package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
- package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
- package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
- package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
- package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
- package/src/wirings/workflow/workflow.types.ts +0 -203
- package/tsconfig.tsbuildinfo +1 -1
- package/src/middleware/timeout.ts +0 -22
- package/src/pikku-response.ts +0 -5
- package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
- package/src/wirings/workflow/dsl/index.ts +0 -36
- package/src/wirings/workflow/graph/index.ts +0 -15
package/src/crypto-utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { WeakKeyMaterialError } from './errors/errors.js'
|
|
2
|
+
|
|
1
3
|
const encoder = new TextEncoder()
|
|
2
4
|
const decoder = new TextDecoder()
|
|
3
5
|
|
|
@@ -45,13 +47,35 @@ const fromBase64Url = (input: string): Uint8Array => {
|
|
|
45
47
|
return base64Decode(base64)
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
const
|
|
50
|
+
const SALT_BYTES = 16
|
|
51
|
+
const IV_BYTES = 12
|
|
52
|
+
const TAG_BYTES = 16
|
|
53
|
+
const PBKDF2_ITERATIONS = 600_000
|
|
54
|
+
|
|
55
|
+
const deriveKey = async (
|
|
56
|
+
secret: string,
|
|
57
|
+
salt: Uint8Array
|
|
58
|
+
): Promise<CryptoKey> => {
|
|
49
59
|
const subtle = getSubtle()
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
|
|
60
|
+
const material = await subtle.importKey(
|
|
61
|
+
'raw',
|
|
62
|
+
encoder.encode(secret),
|
|
63
|
+
{ name: 'PBKDF2' },
|
|
64
|
+
false,
|
|
65
|
+
['deriveKey']
|
|
66
|
+
)
|
|
67
|
+
return subtle.deriveKey(
|
|
68
|
+
{
|
|
69
|
+
name: 'PBKDF2',
|
|
70
|
+
salt: salt as BufferSource,
|
|
71
|
+
iterations: PBKDF2_ITERATIONS,
|
|
72
|
+
hash: 'SHA-256',
|
|
73
|
+
},
|
|
74
|
+
material,
|
|
75
|
+
{ name: 'AES-GCM', length: 256 },
|
|
76
|
+
false,
|
|
77
|
+
['encrypt', 'decrypt']
|
|
78
|
+
)
|
|
55
79
|
}
|
|
56
80
|
|
|
57
81
|
export const encryptJSON = async (
|
|
@@ -63,8 +87,9 @@ export const encryptJSON = async (
|
|
|
63
87
|
throw new Error('WebCrypto not available')
|
|
64
88
|
}
|
|
65
89
|
const subtle = getSubtle()
|
|
66
|
-
const
|
|
67
|
-
const
|
|
90
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES))
|
|
91
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES))
|
|
92
|
+
const key = await deriveKey(secret, salt)
|
|
68
93
|
const plaintext = encoder.encode(JSON.stringify(value))
|
|
69
94
|
const encrypted = await subtle.encrypt(
|
|
70
95
|
{ name: 'AES-GCM', iv },
|
|
@@ -72,9 +97,10 @@ export const encryptJSON = async (
|
|
|
72
97
|
plaintext
|
|
73
98
|
)
|
|
74
99
|
const cipherBytes = new Uint8Array(encrypted)
|
|
75
|
-
const out = new Uint8Array(iv.length + cipherBytes.length)
|
|
76
|
-
out.set(
|
|
77
|
-
out.set(
|
|
100
|
+
const out = new Uint8Array(salt.length + iv.length + cipherBytes.length)
|
|
101
|
+
out.set(salt, 0)
|
|
102
|
+
out.set(iv, salt.length)
|
|
103
|
+
out.set(cipherBytes, salt.length + iv.length)
|
|
78
104
|
return toBase64Url(out)
|
|
79
105
|
}
|
|
80
106
|
|
|
@@ -84,12 +110,13 @@ export const decryptJSON = async <T>(
|
|
|
84
110
|
): Promise<T> => {
|
|
85
111
|
const subtle = getSubtle()
|
|
86
112
|
const data = fromBase64Url(token)
|
|
87
|
-
if (data.length
|
|
113
|
+
if (data.length <= SALT_BYTES + IV_BYTES + TAG_BYTES) {
|
|
88
114
|
throw new Error('Invalid encrypted payload')
|
|
89
115
|
}
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
const
|
|
116
|
+
const salt = data.slice(0, SALT_BYTES)
|
|
117
|
+
const iv = data.slice(SALT_BYTES, SALT_BYTES + IV_BYTES)
|
|
118
|
+
const ciphertext = data.slice(SALT_BYTES + IV_BYTES)
|
|
119
|
+
const key = await deriveKey(secret, salt)
|
|
93
120
|
const decrypted = await subtle.decrypt(
|
|
94
121
|
{ name: 'AES-GCM', iv },
|
|
95
122
|
key,
|
|
@@ -99,58 +126,202 @@ export const decryptJSON = async <T>(
|
|
|
99
126
|
}
|
|
100
127
|
|
|
101
128
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* Each secret gets its own random DEK (data encryption key).
|
|
105
|
-
* The DEK is wrapped (encrypted) by a KEK (key encryption key) — typically an env var.
|
|
106
|
-
* The actual secret is encrypted with the DEK.
|
|
107
|
-
*
|
|
108
|
-
* KEK rotation only re-wraps the DEK, never touches the ciphertext.
|
|
129
|
+
* Namespaces the remote-RPC session key so the same deployment secret used for
|
|
130
|
+
* another purpose derives a different key. See knowledge/crypto.md.
|
|
109
131
|
*/
|
|
132
|
+
export const REMOTE_SESSION_INFO = 'pikku:remote-session'
|
|
110
133
|
|
|
111
|
-
const
|
|
134
|
+
export const MIN_KEY_MATERIAL_LENGTH = 32
|
|
135
|
+
|
|
136
|
+
export const assertStrongKeyMaterial = (
|
|
137
|
+
name: string,
|
|
138
|
+
keyMaterial: string
|
|
139
|
+
): void => {
|
|
140
|
+
if (keyMaterial.length < MIN_KEY_MATERIAL_LENGTH) {
|
|
141
|
+
throw new WeakKeyMaterialError(
|
|
142
|
+
name,
|
|
143
|
+
MIN_KEY_MATERIAL_LENGTH,
|
|
144
|
+
keyMaterial.length
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const expandKeyMaterial = async (
|
|
150
|
+
keyMaterial: string,
|
|
151
|
+
info: string,
|
|
152
|
+
salt: Uint8Array
|
|
153
|
+
): Promise<CryptoKey> => {
|
|
112
154
|
const subtle = getSubtle()
|
|
113
|
-
|
|
155
|
+
const material = await subtle.importKey(
|
|
114
156
|
'raw',
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
157
|
+
encoder.encode(keyMaterial),
|
|
158
|
+
'HKDF',
|
|
159
|
+
false,
|
|
160
|
+
['deriveKey']
|
|
161
|
+
)
|
|
162
|
+
return subtle.deriveKey(
|
|
163
|
+
{
|
|
164
|
+
name: 'HKDF',
|
|
165
|
+
hash: 'SHA-256',
|
|
166
|
+
salt: salt as BufferSource,
|
|
167
|
+
info: encoder.encode(info) as BufferSource,
|
|
168
|
+
},
|
|
169
|
+
material,
|
|
170
|
+
{ name: 'AES-GCM', length: 256 },
|
|
171
|
+
false,
|
|
118
172
|
['encrypt', 'decrypt']
|
|
119
173
|
)
|
|
120
174
|
}
|
|
121
175
|
|
|
122
|
-
export const
|
|
123
|
-
|
|
124
|
-
|
|
176
|
+
export const encryptWithKeyMaterial = async (
|
|
177
|
+
name: string,
|
|
178
|
+
keyMaterial: string,
|
|
179
|
+
info: string,
|
|
180
|
+
value: unknown
|
|
181
|
+
): Promise<string> => {
|
|
182
|
+
assertStrongKeyMaterial(name, keyMaterial)
|
|
183
|
+
const crypto = globalThis.crypto
|
|
184
|
+
if (!crypto?.getRandomValues) {
|
|
185
|
+
throw new Error('WebCrypto not available')
|
|
186
|
+
}
|
|
187
|
+
const subtle = getSubtle()
|
|
188
|
+
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES))
|
|
189
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES))
|
|
190
|
+
const key = await expandKeyMaterial(keyMaterial, info, salt)
|
|
191
|
+
const encrypted = await subtle.encrypt(
|
|
192
|
+
{ name: 'AES-GCM', iv },
|
|
193
|
+
key,
|
|
194
|
+
encoder.encode(JSON.stringify(value))
|
|
195
|
+
)
|
|
196
|
+
const cipherBytes = new Uint8Array(encrypted)
|
|
197
|
+
const out = new Uint8Array(salt.length + iv.length + cipherBytes.length)
|
|
198
|
+
out.set(salt, 0)
|
|
199
|
+
out.set(iv, salt.length)
|
|
200
|
+
out.set(cipherBytes, salt.length + iv.length)
|
|
201
|
+
return toBase64Url(out)
|
|
125
202
|
}
|
|
126
203
|
|
|
127
|
-
export const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
204
|
+
export const decryptWithKeyMaterial = async <T>(
|
|
205
|
+
name: string,
|
|
206
|
+
keyMaterial: string,
|
|
207
|
+
info: string,
|
|
208
|
+
token: string
|
|
209
|
+
): Promise<T> => {
|
|
210
|
+
assertStrongKeyMaterial(name, keyMaterial)
|
|
211
|
+
const subtle = getSubtle()
|
|
212
|
+
const data = fromBase64Url(token)
|
|
213
|
+
if (data.length <= SALT_BYTES + IV_BYTES + TAG_BYTES) {
|
|
214
|
+
throw new Error('Invalid encrypted payload')
|
|
215
|
+
}
|
|
216
|
+
const salt = data.slice(0, SALT_BYTES)
|
|
217
|
+
const iv = data.slice(SALT_BYTES, SALT_BYTES + IV_BYTES)
|
|
218
|
+
const ciphertext = data.slice(SALT_BYTES + IV_BYTES)
|
|
219
|
+
const key = await expandKeyMaterial(keyMaterial, info, salt)
|
|
220
|
+
const decrypted = await subtle.decrypt(
|
|
221
|
+
{ name: 'AES-GCM', iv },
|
|
222
|
+
key,
|
|
223
|
+
ciphertext
|
|
224
|
+
)
|
|
225
|
+
return JSON.parse(decoder.decode(new Uint8Array(decrypted))) as T
|
|
132
226
|
}
|
|
133
227
|
|
|
134
|
-
export const
|
|
135
|
-
|
|
136
|
-
|
|
228
|
+
export const encodeBase64UrlText = (value: string): string =>
|
|
229
|
+
toBase64Url(encoder.encode(value))
|
|
230
|
+
|
|
231
|
+
export const decodeBase64UrlText = (value: string): string =>
|
|
232
|
+
decoder.decode(fromBase64Url(value))
|
|
233
|
+
|
|
234
|
+
const expandSigningKeyMaterial = async (
|
|
235
|
+
keyMaterial: string,
|
|
236
|
+
info: string
|
|
237
|
+
): Promise<CryptoKey> => {
|
|
238
|
+
const subtle = getSubtle()
|
|
239
|
+
const material = await subtle.importKey(
|
|
240
|
+
'raw',
|
|
241
|
+
encoder.encode(keyMaterial),
|
|
242
|
+
'HKDF',
|
|
243
|
+
false,
|
|
244
|
+
['deriveKey']
|
|
245
|
+
)
|
|
246
|
+
return subtle.deriveKey(
|
|
247
|
+
{
|
|
248
|
+
name: 'HKDF',
|
|
249
|
+
hash: 'SHA-256',
|
|
250
|
+
salt: new Uint8Array(0) as BufferSource,
|
|
251
|
+
info: encoder.encode(info) as BufferSource,
|
|
252
|
+
},
|
|
253
|
+
material,
|
|
254
|
+
{ name: 'HMAC', hash: 'SHA-256' },
|
|
255
|
+
false,
|
|
256
|
+
['sign', 'verify']
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* HMAC-SHA256 over `payload` under a key expanded from high-entropy key
|
|
262
|
+
* material, base64url-encoded. The salt is empty by design so the verifier can
|
|
263
|
+
* re-derive the key from `keyMaterial` and `info` alone.
|
|
264
|
+
*/
|
|
265
|
+
export const signWithKeyMaterial = async (
|
|
266
|
+
name: string,
|
|
267
|
+
keyMaterial: string,
|
|
268
|
+
info: string,
|
|
269
|
+
payload: string
|
|
137
270
|
): Promise<string> => {
|
|
138
|
-
|
|
271
|
+
assertStrongKeyMaterial(name, keyMaterial)
|
|
272
|
+
const key = await expandSigningKeyMaterial(keyMaterial, info)
|
|
273
|
+
const signature = await getSubtle().sign(
|
|
274
|
+
'HMAC',
|
|
275
|
+
key,
|
|
276
|
+
encoder.encode(payload) as BufferSource
|
|
277
|
+
)
|
|
278
|
+
return toBase64Url(new Uint8Array(signature))
|
|
139
279
|
}
|
|
140
280
|
|
|
141
|
-
|
|
142
|
-
|
|
281
|
+
/** False — never throws — for a malformed, truncated or mismatched signature. */
|
|
282
|
+
export const verifyWithKeyMaterial = async (
|
|
283
|
+
name: string,
|
|
284
|
+
keyMaterial: string,
|
|
285
|
+
info: string,
|
|
286
|
+
payload: string,
|
|
287
|
+
signature: string
|
|
288
|
+
): Promise<boolean> => {
|
|
289
|
+
assertStrongKeyMaterial(name, keyMaterial)
|
|
290
|
+
const key = await expandSigningKeyMaterial(keyMaterial, info)
|
|
291
|
+
try {
|
|
292
|
+
return await getSubtle().verify(
|
|
293
|
+
'HMAC',
|
|
294
|
+
key,
|
|
295
|
+
fromBase64Url(signature) as BufferSource,
|
|
296
|
+
encoder.encode(payload) as BufferSource
|
|
297
|
+
)
|
|
298
|
+
} catch {
|
|
299
|
+
return false
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const importRawKey = async (rawBytes: Uint8Array): Promise<CryptoKey> => {
|
|
304
|
+
const subtle = getSubtle()
|
|
305
|
+
return subtle.importKey(
|
|
306
|
+
'raw',
|
|
307
|
+
rawBytes.buffer as ArrayBuffer,
|
|
308
|
+
{ name: 'AES-GCM' },
|
|
309
|
+
true,
|
|
310
|
+
['encrypt', 'decrypt']
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const encryptWithCryptoKey = async (
|
|
315
|
+
key: CryptoKey,
|
|
143
316
|
value: unknown
|
|
144
317
|
): Promise<string> => {
|
|
145
318
|
const crypto = globalThis.crypto
|
|
146
319
|
const subtle = getSubtle()
|
|
147
|
-
const iv = crypto.getRandomValues(new Uint8Array(
|
|
148
|
-
const key = await importRawKey(fromBase64Url(dekBase64))
|
|
149
|
-
const plaintext = encoder.encode(JSON.stringify(value))
|
|
320
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES))
|
|
150
321
|
const encrypted = await subtle.encrypt(
|
|
151
322
|
{ name: 'AES-GCM', iv },
|
|
152
323
|
key,
|
|
153
|
-
|
|
324
|
+
encoder.encode(JSON.stringify(value))
|
|
154
325
|
)
|
|
155
326
|
const cipherBytes = new Uint8Array(encrypted)
|
|
156
327
|
const out = new Uint8Array(iv.length + cipherBytes.length)
|
|
@@ -159,18 +330,17 @@ const encryptWithDEK = async (
|
|
|
159
330
|
return toBase64Url(out)
|
|
160
331
|
}
|
|
161
332
|
|
|
162
|
-
const
|
|
163
|
-
|
|
333
|
+
const decryptWithCryptoKey = async <T>(
|
|
334
|
+
key: CryptoKey,
|
|
164
335
|
token: string
|
|
165
336
|
): Promise<T> => {
|
|
166
337
|
const subtle = getSubtle()
|
|
167
338
|
const data = fromBase64Url(token)
|
|
168
|
-
if (data.length <
|
|
339
|
+
if (data.length < IV_BYTES + TAG_BYTES) {
|
|
169
340
|
throw new Error('Invalid encrypted payload')
|
|
170
341
|
}
|
|
171
|
-
const iv = data.slice(0,
|
|
172
|
-
const ciphertext = data.slice(
|
|
173
|
-
const key = await importRawKey(fromBase64Url(dekBase64))
|
|
342
|
+
const iv = data.slice(0, IV_BYTES)
|
|
343
|
+
const ciphertext = data.slice(IV_BYTES)
|
|
174
344
|
const decrypted = await subtle.decrypt(
|
|
175
345
|
{ name: 'AES-GCM', iv },
|
|
176
346
|
key,
|
|
@@ -179,13 +349,71 @@ const decryptWithDEK = async <T>(
|
|
|
179
349
|
return JSON.parse(decoder.decode(new Uint8Array(decrypted))) as T
|
|
180
350
|
}
|
|
181
351
|
|
|
352
|
+
export const generateDEK = async (): Promise<string> => {
|
|
353
|
+
const raw = globalThis.crypto.getRandomValues(new Uint8Array(32))
|
|
354
|
+
return toBase64Url(raw)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* One salt per (deployment, key version), stored beside the wrapped DEKs.
|
|
359
|
+
* See knowledge/crypto.md.
|
|
360
|
+
*/
|
|
361
|
+
export const generateKEKSalt = (): string => {
|
|
362
|
+
const crypto = globalThis.crypto
|
|
363
|
+
if (!crypto?.getRandomValues) {
|
|
364
|
+
throw new Error('WebCrypto not available')
|
|
365
|
+
}
|
|
366
|
+
return toBase64Url(crypto.getRandomValues(new Uint8Array(SALT_BYTES)))
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export const deriveKEK = async (
|
|
370
|
+
passphrase: string,
|
|
371
|
+
salt: string
|
|
372
|
+
): Promise<CryptoKey> => {
|
|
373
|
+
return deriveKey(passphrase, fromBase64Url(salt))
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export const wrapDEK = async (
|
|
377
|
+
kek: CryptoKey,
|
|
378
|
+
plaintextDEK: string
|
|
379
|
+
): Promise<string> => {
|
|
380
|
+
return encryptWithCryptoKey(kek, plaintextDEK)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export const unwrapDEK = async (
|
|
384
|
+
kek: CryptoKey,
|
|
385
|
+
wrappedDEK: string
|
|
386
|
+
): Promise<string> => {
|
|
387
|
+
return decryptWithCryptoKey<string>(kek, wrappedDEK)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const encryptWithDEK = async (
|
|
391
|
+
dekBase64: string,
|
|
392
|
+
value: unknown
|
|
393
|
+
): Promise<string> => {
|
|
394
|
+
return encryptWithCryptoKey(
|
|
395
|
+
await importRawKey(fromBase64Url(dekBase64)),
|
|
396
|
+
value
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const decryptWithDEK = async <T>(
|
|
401
|
+
dekBase64: string,
|
|
402
|
+
token: string
|
|
403
|
+
): Promise<T> => {
|
|
404
|
+
return decryptWithCryptoKey<T>(
|
|
405
|
+
await importRawKey(fromBase64Url(dekBase64)),
|
|
406
|
+
token
|
|
407
|
+
)
|
|
408
|
+
}
|
|
409
|
+
|
|
182
410
|
export interface EnvelopeEncryptResult {
|
|
183
411
|
ciphertext: string
|
|
184
412
|
wrappedDEK: string
|
|
185
413
|
}
|
|
186
414
|
|
|
187
415
|
export const envelopeEncrypt = async (
|
|
188
|
-
kek:
|
|
416
|
+
kek: CryptoKey,
|
|
189
417
|
value: unknown
|
|
190
418
|
): Promise<EnvelopeEncryptResult> => {
|
|
191
419
|
const dek = await generateDEK()
|
|
@@ -195,7 +423,7 @@ export const envelopeEncrypt = async (
|
|
|
195
423
|
}
|
|
196
424
|
|
|
197
425
|
export const envelopeDecrypt = async <T>(
|
|
198
|
-
kek:
|
|
426
|
+
kek: CryptoKey,
|
|
199
427
|
ciphertext: string,
|
|
200
428
|
wrappedDEK: string
|
|
201
429
|
): Promise<T> => {
|
|
@@ -204,8 +432,8 @@ export const envelopeDecrypt = async <T>(
|
|
|
204
432
|
}
|
|
205
433
|
|
|
206
434
|
export const envelopeRewrap = async (
|
|
207
|
-
oldKEK:
|
|
208
|
-
newKEK:
|
|
435
|
+
oldKEK: CryptoKey,
|
|
436
|
+
newKEK: CryptoKey,
|
|
209
437
|
wrappedDEK: string
|
|
210
438
|
): Promise<string> => {
|
|
211
439
|
const dek = await unwrapDEK(oldKEK, wrappedDEK)
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
// would make a plain value (e.g. `string`) unassignable to a branded column
|
|
3
|
-
// (`Private<string>`), which breaks ordinary Kysely query operands —
|
|
4
|
-
// `where('email', '=', someString)`, inserts, and `.set(...)`. Making it
|
|
5
|
-
// optional keeps the brand structurally present (so the inspector's PKU910
|
|
6
|
-
// output check still detects it) while allowing plain values to flow IN.
|
|
7
|
-
// See `findPiiPaths` in @pikku/inspector, which reads the level union-aware.
|
|
1
|
+
// knowledge: decisions/internals/core-data-classification-brand-is-an-optional-property.md
|
|
8
2
|
export type Private<T> = T & { readonly __classification__?: 'private' }
|
|
9
3
|
export type Pii<T> = T & { readonly __classification__?: 'pii' }
|
|
10
4
|
export type Secret<T> = T & { readonly __classification__?: 'secret' }
|
|
@@ -354,14 +354,12 @@ describe('pikkuDevReloader', { concurrency: false }, () => {
|
|
|
354
354
|
pikkuDir: tmpDir,
|
|
355
355
|
})
|
|
356
356
|
|
|
357
|
-
// Write updated function via file system and let the watcher pick it up
|
|
358
357
|
const jsV2 = `export const hotTask = { func: async () => { return { reloaded: true }; }, auth: false };\n`
|
|
359
358
|
await writeFile(join(tmpDir, 'hotTask.js'), jsV2)
|
|
360
359
|
await writeFile(join(tmpDir, 'hotTask.ts'), `// trigger ${Date.now()}`)
|
|
361
360
|
|
|
362
361
|
await wait(300)
|
|
363
362
|
|
|
364
|
-
// Verify the function was reloaded via the watcher
|
|
365
363
|
const reloadLog = mockLogger
|
|
366
364
|
.getLogs()
|
|
367
365
|
.find(
|
|
@@ -370,8 +368,6 @@ describe('pikkuDevReloader', { concurrency: false }, () => {
|
|
|
370
368
|
)
|
|
371
369
|
assert.ok(reloadLog, 'Should log hot-reload for hotTask')
|
|
372
370
|
|
|
373
|
-
// runScheduledTask uses runPikkuFunc which reads from the functions Map,
|
|
374
|
-
// so it will pick up the hot-reloaded function (no longer sets taskResult.ref)
|
|
375
371
|
await runScheduledTask({ name: 'hotTask' })
|
|
376
372
|
|
|
377
373
|
// The reloaded function no longer sets taskResult.ref, so it should
|
package/src/dev/hot-reload.ts
CHANGED
|
@@ -52,12 +52,6 @@ const findCompiledFile = async (
|
|
|
52
52
|
return null
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// Changed user files are re-run through an evictable module runner keyed by a
|
|
56
|
-
// stable path (createModuleRunner), NOT re-imported under a fresh URL. A
|
|
57
|
-
// fresh-URL import (a `data:` URL on Node, a uniquely-named temp sibling on
|
|
58
|
-
// Bun) permanently leaks a record in the native ESM loader map on every
|
|
59
|
-
// reload, OOMing long editing sessions; the runner overwrites a single slot so
|
|
60
|
-
// the previous module is collected. See ./module-runner.ts.
|
|
61
55
|
const isWatchedTsFile = (filename: string): boolean => {
|
|
62
56
|
return (
|
|
63
57
|
filename.endsWith('.ts') &&
|
|
@@ -110,17 +104,12 @@ export async function pikkuDevReloader(
|
|
|
110
104
|
return
|
|
111
105
|
}
|
|
112
106
|
|
|
113
|
-
// Register every function-config export
|
|
114
|
-
// adding new ones
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
// that map is silently discarded when it restores the original.
|
|
120
|
-
// Schemas are NOT touched here: `input`/`output` hold raw zod schemas,
|
|
121
|
-
// while the schema map carries codegen-generated JSON schemas — mixing the
|
|
122
|
-
// two crashed every reload. Fresh JSON schemas arrive via
|
|
123
|
-
// reloadGeneratedMeta once codegen has re-emitted them.
|
|
107
|
+
// Register every function-config export, replacing known functions and
|
|
108
|
+
// adding new ones. Write into the map captured at startup, NOT pikkuState's
|
|
109
|
+
// current one: a dev-server watcher may have temporarily swapped in a
|
|
110
|
+
// codegen-scoped map, whose writes are discarded when it restores.
|
|
111
|
+
// Schemas are NOT touched here: `input`/`output` hold raw zod schemas while
|
|
112
|
+
// the schema map carries codegen JSON schemas; mixing them crashed reloads.
|
|
124
113
|
for (const [exportName, exportValue] of Object.entries(mod)) {
|
|
125
114
|
if (!isFunctionConfig(exportValue)) continue
|
|
126
115
|
const isNew = !functionsMap.has(exportName)
|
|
@@ -129,10 +118,9 @@ export async function pikkuDevReloader(
|
|
|
129
118
|
else reloadedNames.push(exportName)
|
|
130
119
|
}
|
|
131
120
|
|
|
132
|
-
// Re-importing
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
// wiring-only file edit rebuilds the route matchers too.
|
|
121
|
+
// Re-importing re-ran the module’s wire* side effects, so reset the router
|
|
122
|
+
// and caches even when no function export changed — a wiring-only edit has
|
|
123
|
+
// to rebuild the route matchers too.
|
|
136
124
|
clearMiddlewareCache()
|
|
137
125
|
clearPermissionsCache()
|
|
138
126
|
clearChannelMiddlewareCache()
|
|
@@ -149,9 +137,8 @@ export async function pikkuDevReloader(
|
|
|
149
137
|
|
|
150
138
|
let debounceTimer: ReturnType<typeof setTimeout> | undefined
|
|
151
139
|
const pendingChanges = new Set<string>()
|
|
152
|
-
// Files re-imported since the last reimportPending() drain
|
|
153
|
-
//
|
|
154
|
-
// were skipped for missing meta (a NEW route) run again with fresh meta.
|
|
140
|
+
// Files re-imported since the last reimportPending() drain, re-run after the
|
|
141
|
+
// dev server's codegen pass so registrations skipped for missing meta retry.
|
|
155
142
|
const postCodegenQueue = new Set<string>()
|
|
156
143
|
|
|
157
144
|
const safeHandleFileChange = async (file: string) => {
|
|
@@ -206,12 +193,6 @@ export async function pikkuDevReloader(
|
|
|
206
193
|
}
|
|
207
194
|
moduleRunner.clear()
|
|
208
195
|
},
|
|
209
|
-
// Drain the queue of recently re-imported files and import them again.
|
|
210
|
-
// A dev-server watcher calls this AFTER its codegen pass has refreshed
|
|
211
|
-
// the generated meta (reloadGeneratedMeta): wire* registrations skip
|
|
212
|
-
// routes whose meta doesn't exist yet, so a wiring file changed
|
|
213
|
-
// alongside a NEW function only registers its new route when
|
|
214
|
-
// re-imported after the fresh meta has landed.
|
|
215
196
|
reimportPending: async () => {
|
|
216
197
|
const files = [...postCodegenQueue]
|
|
217
198
|
postCodegenQueue.clear()
|
package/src/dev/module-runner.ts
CHANGED
|
@@ -5,46 +5,26 @@ import { pathToFileURL } from 'node:url'
|
|
|
5
5
|
import { compileFunction } from 'node:vm'
|
|
6
6
|
import type { transformSync as EsbuildTransformSync } from 'esbuild'
|
|
7
7
|
|
|
8
|
-
// Evictable module runner for hot-reload.
|
|
9
|
-
//
|
|
10
|
-
// Re-importing a changed user file through the native ESM loader (a fresh
|
|
11
|
-
// `data:` URL on Node, a fresh temp-file path on Bun) is unbounded: the loader
|
|
12
|
-
// keeps a `Map<url, moduleRecord>` for the realm lifetime with no eviction API,
|
|
13
|
-
// so every reload permanently leaks a module record and the dev server
|
|
14
|
-
// eventually OOMs (worse on Bun). Instead we own the registry: transpile the
|
|
15
|
-
// source to CJS (esbuild), run it as a plain function via `vm.compileFunction`
|
|
16
|
-
// — which produces a garbage-collectable function rather than a permanent
|
|
17
|
-
// loader entry — and store the resulting exports under a STABLE path key. A
|
|
18
|
-
// reload overwrites that one slot, so the previous module becomes unreachable
|
|
19
|
-
// and is collected. `import`s inside the user file are delegated to
|
|
20
|
-
// `createRequire`, whose resolution matches the native loader AND returns the
|
|
21
|
-
// same live singletons (Node/Bun share the require/import module cache), so
|
|
22
|
-
// top-level side effects (wireHTTP et al) mutate the same running services.
|
|
23
8
|
type EsbuildTransform = typeof EsbuildTransformSync
|
|
24
9
|
|
|
25
10
|
let transformSync: EsbuildTransform | undefined
|
|
26
11
|
|
|
27
12
|
const loadTransform = async (): Promise<EsbuildTransform> => {
|
|
28
13
|
if (transformSync) return transformSync
|
|
29
|
-
// esbuild is a dev-only dependency
|
|
30
|
-
//
|
|
31
|
-
// in production runtimes (the `./dev` export is dev-only).
|
|
14
|
+
// esbuild is a dev-only dependency hoisted from @pikku/cli at runtime; the
|
|
15
|
+
// `./dev` export is dev-only so it is never loaded in production runtimes.
|
|
32
16
|
const esbuild = await import('esbuild')
|
|
33
17
|
transformSync = esbuild.transformSync
|
|
34
18
|
return transformSync
|
|
35
19
|
}
|
|
36
20
|
|
|
37
21
|
export interface PikkuModuleRunner {
|
|
38
|
-
/** Run a user module by absolute path
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* caller can keep the previously-loaded code. */
|
|
22
|
+
/** Run a user module by absolute path. Repeated runs of one path overwrite a
|
|
23
|
+
* single registry slot. Returns `null` on failure so the caller can keep the
|
|
24
|
+
* previously-loaded code. */
|
|
42
25
|
run: (absPath: string) => Promise<Record<string, unknown> | null>
|
|
43
|
-
/** Drop a single module from the registry. */
|
|
44
26
|
evict: (absPath: string) => void
|
|
45
|
-
/** Drop every module from the registry. */
|
|
46
27
|
clear: () => void
|
|
47
|
-
/** Number of modules currently held. */
|
|
48
28
|
readonly size: number
|
|
49
29
|
}
|
|
50
30
|
|
|
@@ -58,10 +38,6 @@ export const createModuleRunner = (): PikkuModuleRunner => {
|
|
|
58
38
|
try {
|
|
59
39
|
const transform = await loadTransform()
|
|
60
40
|
const source = await readFile(absPath, 'utf-8')
|
|
61
|
-
// No sourcemap: an inline sourcemap embeds a base64 copy of the source
|
|
62
|
-
// that the engine retains per compile, reintroducing linear growth on
|
|
63
|
-
// Node — the exact leak this runner exists to remove. `filename` still
|
|
64
|
-
// anchors stack traces to the user file.
|
|
65
41
|
const { code } = transform(source, {
|
|
66
42
|
loader: absPath.endsWith('.ts') ? 'ts' : 'js',
|
|
67
43
|
format: 'cjs',
|
|
@@ -81,9 +57,8 @@ export const createModuleRunner = (): PikkuModuleRunner => {
|
|
|
81
57
|
registry.set(absPath, moduleObj.exports)
|
|
82
58
|
return moduleObj.exports
|
|
83
59
|
} catch {
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// `cjs` form). Return null so the caller keeps the previously-loaded code.
|
|
60
|
+
// A bad edit, or the one known limitation: a file using top-level
|
|
61
|
+
// `await`, which cannot be emitted in `cjs` form.
|
|
87
62
|
return null
|
|
88
63
|
}
|
|
89
64
|
}
|