@pikku/core 0.12.71 → 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 +848 -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 +40 -30
- 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 -11
- package/dist/handle-error.js +6 -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 +7 -17
- package/dist/schema.js +30 -18
- 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 +1 -100
- package/dist/wirings/http/http-runner.js +12 -166
- package/dist/wirings/http/http.types.d.ts +16 -55
- package/dist/wirings/http/index.d.ts +2 -1
- package/dist/wirings/http/index.js +1 -1
- 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 +6 -36
- package/dist/wirings/http/pikku-fetch-http-request.js +56 -50
- 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 +2 -0
- package/dist/wirings/mcp/mcp-runner.js +6 -16
- 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 -2
- 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 +75 -7
- package/src/function/function-runner.ts +73 -30
- 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/gopass-secrets-removed.test.ts +51 -0
- package/src/handle-error.test.ts +108 -1
- package/src/handle-error.ts +8 -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.test.ts +103 -0
- package/src/schema.ts +35 -18
- 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 +12 -168
- package/src/wirings/http/http.types.ts +17 -62
- package/src/wirings/http/index.ts +5 -1
- package/src/wirings/http/log-http-routes.ts +0 -4
- package/src/wirings/http/pikku-fetch-http-request.test.ts +88 -7
- package/src/wirings/http/pikku-fetch-http-request.ts +74 -50
- 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.test.ts +40 -0
- package/src/wirings/mcp/mcp-runner.ts +9 -15
- 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/services/gopass-secrets.ts +0 -78
- 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
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { describe, test, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { buildRemoteHeaders } from './remote.js'
|
|
4
|
+
import { pikkuRemoteAuthMiddleware } from './middleware/remote-auth.js'
|
|
5
|
+
import { resetPikkuState } from './pikku-state.js'
|
|
6
|
+
import { WeakKeyMaterialError } from './errors/errors.js'
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
resetPikkuState()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const STRONG_SECRET = 'a'.repeat(43)
|
|
13
|
+
const WEAK_SECRET = 'dev-remote-secret'
|
|
14
|
+
|
|
15
|
+
const createSecrets = (secret: string) => ({
|
|
16
|
+
getSecret: async (key: string) => {
|
|
17
|
+
if (key === 'PIKKU_REMOTE_SECRET') return secret
|
|
18
|
+
throw new Error(`Secret ${key} not found`)
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Signing is deliberately free here so the measurement isolates key derivation.
|
|
24
|
+
*/
|
|
25
|
+
const createJWT = () => ({
|
|
26
|
+
encode: async (_expiresIn: unknown, payload: unknown) =>
|
|
27
|
+
Buffer.from(JSON.stringify(payload)).toString('base64url'),
|
|
28
|
+
decode: async (token: string) =>
|
|
29
|
+
JSON.parse(Buffer.from(token, 'base64url').toString('utf-8')),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const createRequest = (
|
|
33
|
+
headers: Record<string, string>,
|
|
34
|
+
path = '/remote/rpc/myFunc'
|
|
35
|
+
) => ({
|
|
36
|
+
header: (name: string) => headers[name.toLowerCase()] || headers[name],
|
|
37
|
+
path: () => path,
|
|
38
|
+
method: () => 'POST',
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const roundTrip = async (secret: string, session: unknown) => {
|
|
42
|
+
const jwt = createJWT()
|
|
43
|
+
const secrets = createSecrets(secret)
|
|
44
|
+
|
|
45
|
+
const headers = await buildRemoteHeaders(
|
|
46
|
+
jwt as any,
|
|
47
|
+
secrets as any,
|
|
48
|
+
'myFunc',
|
|
49
|
+
session
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
let received: unknown
|
|
53
|
+
await pikkuRemoteAuthMiddleware(
|
|
54
|
+
{ secrets, jwt } as any,
|
|
55
|
+
{
|
|
56
|
+
http: {
|
|
57
|
+
request: createRequest({ authorization: headers.authorization! }),
|
|
58
|
+
},
|
|
59
|
+
setSession: async (s: unknown) => {
|
|
60
|
+
received = s
|
|
61
|
+
},
|
|
62
|
+
} as any,
|
|
63
|
+
async () => {}
|
|
64
|
+
)
|
|
65
|
+
return received
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
describe('remote RPC session round trip', () => {
|
|
69
|
+
test('round-trips the session through header build and middleware verify', async () => {
|
|
70
|
+
const session = { userId: 'user-1', role: 'admin' }
|
|
71
|
+
assert.deepStrictEqual(await roundTrip(STRONG_SECRET, session), session)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('a header built with one secret is rejected by a peer holding another', async () => {
|
|
75
|
+
const jwt = createJWT()
|
|
76
|
+
const headers = await buildRemoteHeaders(
|
|
77
|
+
jwt as any,
|
|
78
|
+
createSecrets(STRONG_SECRET) as any,
|
|
79
|
+
'myFunc',
|
|
80
|
+
{ userId: 'user-1' }
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
await assert.rejects(() =>
|
|
84
|
+
pikkuRemoteAuthMiddleware(
|
|
85
|
+
{ secrets: createSecrets('b'.repeat(43)), jwt } as any,
|
|
86
|
+
{
|
|
87
|
+
http: {
|
|
88
|
+
request: createRequest({ authorization: headers.authorization! }),
|
|
89
|
+
},
|
|
90
|
+
setSession: async () => {},
|
|
91
|
+
} as any,
|
|
92
|
+
async () => {}
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('a full round trip stays under the per-hop latency budget', async () => {
|
|
98
|
+
const session = { userId: 'user-1', role: 'admin' }
|
|
99
|
+
|
|
100
|
+
// Warm up so the measurement excludes module/JIT startup.
|
|
101
|
+
await roundTrip(STRONG_SECRET, session)
|
|
102
|
+
|
|
103
|
+
const iterations = 5
|
|
104
|
+
const start = performance.now()
|
|
105
|
+
for (let i = 0; i < iterations; i++) {
|
|
106
|
+
await roundTrip(STRONG_SECRET, session)
|
|
107
|
+
}
|
|
108
|
+
const perRoundTrip = (performance.now() - start) / iterations
|
|
109
|
+
|
|
110
|
+
assert.ok(
|
|
111
|
+
perRoundTrip < 20,
|
|
112
|
+
`remote RPC round trip took ${perRoundTrip.toFixed(1)}ms, budget is 20ms`
|
|
113
|
+
)
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
describe('PIKKU_REMOTE_SECRET strength', () => {
|
|
118
|
+
test('buildRemoteHeaders rejects a secret shorter than 32 characters', async () => {
|
|
119
|
+
await assert.rejects(
|
|
120
|
+
() =>
|
|
121
|
+
buildRemoteHeaders(
|
|
122
|
+
createJWT() as any,
|
|
123
|
+
createSecrets(WEAK_SECRET) as any,
|
|
124
|
+
'myFunc',
|
|
125
|
+
{ userId: 'user-1' }
|
|
126
|
+
),
|
|
127
|
+
(err: unknown) => err instanceof WeakKeyMaterialError
|
|
128
|
+
)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('buildRemoteHeaders rejects a weak secret even with no session to encrypt', async () => {
|
|
132
|
+
await assert.rejects(
|
|
133
|
+
() =>
|
|
134
|
+
buildRemoteHeaders(
|
|
135
|
+
createJWT() as any,
|
|
136
|
+
createSecrets(WEAK_SECRET) as any,
|
|
137
|
+
'myFunc'
|
|
138
|
+
),
|
|
139
|
+
(err: unknown) => err instanceof WeakKeyMaterialError
|
|
140
|
+
)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
test('the middleware rejects a weak secret rather than authenticating with it', async () => {
|
|
144
|
+
const jwt = createJWT()
|
|
145
|
+
const headers = await buildRemoteHeaders(
|
|
146
|
+
jwt as any,
|
|
147
|
+
createSecrets(STRONG_SECRET) as any,
|
|
148
|
+
'myFunc',
|
|
149
|
+
{ userId: 'user-1' }
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
await assert.rejects(
|
|
153
|
+
() =>
|
|
154
|
+
pikkuRemoteAuthMiddleware(
|
|
155
|
+
{ secrets: createSecrets(WEAK_SECRET), jwt } as any,
|
|
156
|
+
{
|
|
157
|
+
http: {
|
|
158
|
+
request: createRequest({ authorization: headers.authorization! }),
|
|
159
|
+
},
|
|
160
|
+
setSession: async () => {},
|
|
161
|
+
} as any,
|
|
162
|
+
async () => {}
|
|
163
|
+
),
|
|
164
|
+
(err: unknown) => err instanceof WeakKeyMaterialError
|
|
165
|
+
)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('a secret of exactly 32 characters is accepted', async () => {
|
|
169
|
+
const session = { userId: 'user-1' }
|
|
170
|
+
assert.deepStrictEqual(await roundTrip('x'.repeat(32), session), session)
|
|
171
|
+
})
|
|
172
|
+
})
|
package/src/remote.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { JWTService } from './services/jwt-service.js'
|
|
2
2
|
import type { SecretService } from './services/secret-service.js'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
assertStrongKeyMaterial,
|
|
5
|
+
encryptWithKeyMaterial,
|
|
6
|
+
REMOTE_SESSION_INFO,
|
|
7
|
+
} from './crypto-utils.js'
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
|
-
*
|
|
7
|
-
* pikkuRemoteAuthMiddleware on the receiving end.
|
|
8
|
-
*
|
|
9
|
-
* Used by all deployment services (Kysely, Redis, MongoDB, Lambda, CF, Azure)
|
|
10
|
-
* regardless of transport (HTTP, Lambda Invoke, service bindings).
|
|
10
|
+
* Authorization headers carrying a JWT-signed session and traceId for
|
|
11
|
+
* `pikkuRemoteAuthMiddleware` on the receiving end. Used by every deployment
|
|
12
|
+
* service regardless of transport (HTTP, Lambda Invoke, service bindings).
|
|
11
13
|
*/
|
|
12
14
|
export async function buildRemoteHeaders(
|
|
13
15
|
jwt: JWTService | undefined,
|
|
@@ -27,8 +29,16 @@ export async function buildRemoteHeaders(
|
|
|
27
29
|
} catch {}
|
|
28
30
|
|
|
29
31
|
if (secret && jwt) {
|
|
32
|
+
assertStrongKeyMaterial('PIKKU_REMOTE_SECRET', secret)
|
|
30
33
|
const sessionEnc = session
|
|
31
|
-
? await
|
|
34
|
+
? await encryptWithKeyMaterial(
|
|
35
|
+
'PIKKU_REMOTE_SECRET',
|
|
36
|
+
secret,
|
|
37
|
+
REMOTE_SESSION_INFO,
|
|
38
|
+
{
|
|
39
|
+
session,
|
|
40
|
+
}
|
|
41
|
+
)
|
|
32
42
|
: undefined
|
|
33
43
|
const token = await jwt.encode(
|
|
34
44
|
{ value: 5, unit: 'minute' },
|
package/src/schema.test.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as assert from 'assert'
|
|
|
3
3
|
import {
|
|
4
4
|
addSchema,
|
|
5
5
|
getSchema,
|
|
6
|
+
applyDefaultsFromSchema,
|
|
6
7
|
coerceTopLevelDataFromSchema,
|
|
7
8
|
validateSchema,
|
|
8
9
|
compileAllSchemas,
|
|
@@ -111,6 +112,108 @@ describe('Schema', () => {
|
|
|
111
112
|
})
|
|
112
113
|
})
|
|
113
114
|
|
|
115
|
+
describe('applyDefaultsFromSchema', () => {
|
|
116
|
+
before(() => {
|
|
117
|
+
addSchema('defaultsSchema', {
|
|
118
|
+
properties: {
|
|
119
|
+
page: { type: 'number', default: 1 },
|
|
120
|
+
limit: { type: 'number', default: 50 },
|
|
121
|
+
addons: { type: 'array', default: [] },
|
|
122
|
+
mode: { type: 'string', default: 'manual' },
|
|
123
|
+
enabled: { type: 'boolean', default: true },
|
|
124
|
+
name: { type: 'string' },
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
addSchema('noDefaultsSchema', {
|
|
129
|
+
properties: { name: { type: 'string' } },
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
addSchema('booleanPropSchema', {
|
|
133
|
+
properties: { isActive: true, page: { type: 'number', default: 1 } },
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('should fill in absent properties from their default', () => {
|
|
138
|
+
const data = applyDefaultsFromSchema('defaultsSchema', {})
|
|
139
|
+
assert.strictEqual(data.page, 1)
|
|
140
|
+
assert.strictEqual(data.limit, 50)
|
|
141
|
+
assert.strictEqual(data.mode, 'manual')
|
|
142
|
+
assert.strictEqual(data.enabled, true)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('should not overwrite a supplied value', () => {
|
|
146
|
+
const data = applyDefaultsFromSchema('defaultsSchema', {
|
|
147
|
+
page: 7,
|
|
148
|
+
limit: 200,
|
|
149
|
+
})
|
|
150
|
+
assert.strictEqual(data.page, 7)
|
|
151
|
+
assert.strictEqual(data.limit, 200)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// `false` and `0` are the values a truthiness check silently replaces, and
|
|
155
|
+
// the reason this tests presence rather than falsiness.
|
|
156
|
+
test('should not overwrite a supplied falsy value', () => {
|
|
157
|
+
const data = applyDefaultsFromSchema('defaultsSchema', {
|
|
158
|
+
page: 0,
|
|
159
|
+
enabled: false,
|
|
160
|
+
})
|
|
161
|
+
assert.strictEqual(data.page, 0)
|
|
162
|
+
assert.strictEqual(data.enabled, false)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
test('should fill defaults into nullish data', () => {
|
|
166
|
+
assert.strictEqual(
|
|
167
|
+
applyDefaultsFromSchema('defaultsSchema', undefined).page,
|
|
168
|
+
1
|
|
169
|
+
)
|
|
170
|
+
assert.strictEqual(
|
|
171
|
+
applyDefaultsFromSchema('defaultsSchema', null).limit,
|
|
172
|
+
50
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test('should leave properties without a default absent', () => {
|
|
177
|
+
const data = applyDefaultsFromSchema('defaultsSchema', {})
|
|
178
|
+
assert.ok(!('name' in data))
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Two requests sharing one array default would let the first request's
|
|
182
|
+
// pushes show up in the second.
|
|
183
|
+
test('should clone object and array defaults per call', () => {
|
|
184
|
+
const first = applyDefaultsFromSchema('defaultsSchema', {})
|
|
185
|
+
const second = applyDefaultsFromSchema('defaultsSchema', {})
|
|
186
|
+
first.addons.push('leaked')
|
|
187
|
+
assert.deepStrictEqual(second.addons, [])
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('should return the same data when the schema has no defaults', () => {
|
|
191
|
+
const data = { name: 'x' }
|
|
192
|
+
assert.strictEqual(
|
|
193
|
+
applyDefaultsFromSchema('noDefaultsSchema', data),
|
|
194
|
+
data
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('should return data untouched for an unknown schema', () => {
|
|
199
|
+
const data = { name: 'x' }
|
|
200
|
+
assert.strictEqual(applyDefaultsFromSchema('nonExistent', data), data)
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
test('should leave a primitive body for the validator to reject', () => {
|
|
204
|
+
assert.strictEqual(
|
|
205
|
+
applyDefaultsFromSchema('defaultsSchema', 'nope'),
|
|
206
|
+
'nope'
|
|
207
|
+
)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
test('should skip boolean schema properties', () => {
|
|
211
|
+
const data = applyDefaultsFromSchema('booleanPropSchema', {})
|
|
212
|
+
assert.strictEqual(data.page, 1)
|
|
213
|
+
assert.ok(!('isActive' in data))
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
114
217
|
describe('validateSchema', () => {
|
|
115
218
|
beforeEach(() => {
|
|
116
219
|
resetPikkuState()
|
package/src/schema.ts
CHANGED
|
@@ -9,13 +9,6 @@ import { pikkuState, getAllPackageStates } from './pikku-state.js'
|
|
|
9
9
|
const schemaKey = (name: string, packageName: string | null): string =>
|
|
10
10
|
packageName ? `${packageName}:${name}` : name
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* Adds a schema to the schemas map for a specific package.
|
|
14
|
-
* @param name - The name of the schema.
|
|
15
|
-
* @param value - The schema value.
|
|
16
|
-
* @param packageName - The package name (null for main package, '@scope/package' for addon packages).
|
|
17
|
-
* @ignore
|
|
18
|
-
*/
|
|
19
12
|
export const addSchema = (
|
|
20
13
|
name: string,
|
|
21
14
|
value: any,
|
|
@@ -25,13 +18,6 @@ export const addSchema = (
|
|
|
25
18
|
pikkuState(packageName, 'misc', 'schemas').set(name, schema)
|
|
26
19
|
}
|
|
27
20
|
|
|
28
|
-
/**
|
|
29
|
-
* Retrieves a schema from the schemas map for a specific package.
|
|
30
|
-
* @param name - The name of the schema.
|
|
31
|
-
* @param packageName - The package name (null for main package, '@scope/package' for addon packages).
|
|
32
|
-
* @returns The schema value or undefined if not found.
|
|
33
|
-
* @ignore
|
|
34
|
-
*/
|
|
35
21
|
export const getSchema = (
|
|
36
22
|
name: string,
|
|
37
23
|
packageName: string | null = null
|
|
@@ -39,10 +25,6 @@ export const getSchema = (
|
|
|
39
25
|
return pikkuState(packageName, 'misc', 'schemas').get(name)
|
|
40
26
|
}
|
|
41
27
|
|
|
42
|
-
/**
|
|
43
|
-
* Loads a schema and compiles it into a validator.
|
|
44
|
-
* @param logger - A logger for logging information.
|
|
45
|
-
*/
|
|
46
28
|
export const compileAllSchemas = (
|
|
47
29
|
logger: Logger,
|
|
48
30
|
schemaService?: SchemaService
|
|
@@ -94,6 +76,41 @@ const validateAllSchemasLoaded = (
|
|
|
94
76
|
}
|
|
95
77
|
}
|
|
96
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Fills in absent top-level properties from their schema `default`. Applied
|
|
81
|
+
* unconditionally: a default belongs to the schema, not to the transport the
|
|
82
|
+
* call arrived on, and runs before coercion so a defaulted and a supplied
|
|
83
|
+
* value are treated identically from here on. Values are cloned so an object
|
|
84
|
+
* or array default is never shared as one mutable instance across requests.
|
|
85
|
+
*/
|
|
86
|
+
export const applyDefaultsFromSchema = (
|
|
87
|
+
schemaName: string,
|
|
88
|
+
data: any,
|
|
89
|
+
packageName: string | null = null
|
|
90
|
+
) => {
|
|
91
|
+
const schema = pikkuState(packageName, 'misc', 'schemas').get(schemaName)
|
|
92
|
+
if (!schema?.properties) return data
|
|
93
|
+
|
|
94
|
+
// A primitive body cannot carry named properties; leave it for the validator
|
|
95
|
+
// to reject rather than reshaping it into something that would pass.
|
|
96
|
+
if (data != null && typeof data !== 'object') return data
|
|
97
|
+
|
|
98
|
+
let result = data
|
|
99
|
+
for (const key in schema.properties) {
|
|
100
|
+
const property = schema.properties[key]
|
|
101
|
+
if (typeof property === 'boolean' || !('default' in property)) {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
// Allocated only once a default is actually found, so a schema without any
|
|
105
|
+
// leaves the caller's data (and its absence) exactly as it was.
|
|
106
|
+
result ??= {}
|
|
107
|
+
if (result[key] === undefined) {
|
|
108
|
+
result[key] = structuredClone(property.default)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result
|
|
112
|
+
}
|
|
113
|
+
|
|
97
114
|
export const coerceTopLevelDataFromSchema = (
|
|
98
115
|
schemaName: string,
|
|
99
116
|
data: any,
|
package/src/scopes.ts
CHANGED
|
@@ -5,13 +5,9 @@ const SEPARATOR = ':'
|
|
|
5
5
|
const WILDCARD = '*'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Every grant that would satisfy `scope`: the scope itself, a wildcard
|
|
9
9
|
* directly beneath it, a wildcard at each ancestor level, and each plain
|
|
10
|
-
* ancestor id
|
|
11
|
-
*
|
|
12
|
-
* For `admin:invoices:create` that is:
|
|
13
|
-
* admin:invoices:create, admin:invoices:create:*, *, admin:*, admin:invoices:*,
|
|
14
|
-
* admin, admin:invoices
|
|
10
|
+
* ancestor id.
|
|
15
11
|
*/
|
|
16
12
|
const satisfyingGrants = (scope: string): string[] => {
|
|
17
13
|
const segments = scope.split(SEPARATOR)
|
|
@@ -25,28 +21,10 @@ const satisfyingGrants = (scope: string): string[] => {
|
|
|
25
21
|
return grants
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
/**
|
|
29
|
-
* Checks whether `held` satisfies a single required scope.
|
|
30
|
-
*
|
|
31
|
-
* A grant satisfies a requirement when it is the scope itself, a plain ancestor
|
|
32
|
-
* (`admin` covers `admin:invoices:create`), a wildcard at or above it (`admin:*`
|
|
33
|
-
* covers `admin` and `admin:invoices:create`), or the bare `*`. A narrower grant
|
|
34
|
-
* never satisfies a broader requirement — `admin:invoices` does not grant
|
|
35
|
-
* `admin`.
|
|
36
|
-
*/
|
|
37
24
|
const holds = (held: ReadonlySet<string>, scope: string): boolean =>
|
|
38
25
|
satisfyingGrants(scope).some((grant) => held.has(grant))
|
|
39
26
|
|
|
40
|
-
/**
|
|
41
|
-
* The first required scope a set of held grants does not satisfy, or `null`
|
|
42
|
-
* when every one is satisfied.
|
|
43
|
-
*
|
|
44
|
-
* Scopes are an AND gate: every entry in `required` must be satisfied. This is
|
|
45
|
-
* deliberately distinct from `permissions`, which OR together — a scope can
|
|
46
|
-
* only ever narrow access, so adding one to a function can never widen it.
|
|
47
|
-
*
|
|
48
|
-
* Fails closed: an absent `held` satisfies nothing.
|
|
49
|
-
*/
|
|
27
|
+
/** The first required scope `held` does not satisfy, or `null`. Fails closed. */
|
|
50
28
|
const firstUnsatisfied = (
|
|
51
29
|
required: readonly string[] | undefined,
|
|
52
30
|
held: Iterable<string> | undefined
|
|
@@ -65,17 +43,8 @@ const firstUnsatisfied = (
|
|
|
65
43
|
}
|
|
66
44
|
|
|
67
45
|
/**
|
|
68
|
-
* Whether a set of held grants satisfies every required scope.
|
|
69
|
-
*
|
|
70
46
|
* The non-throwing counterpart to {@link verifyScopes}, for deciding rather
|
|
71
|
-
* than enforcing
|
|
72
|
-
* it is not satisfied, rather than rejecting the request outright.
|
|
73
|
-
*
|
|
74
|
-
* Fails closed: an absent or empty `held` satisfies nothing. An empty
|
|
75
|
-
* `required` is satisfied by anything.
|
|
76
|
-
*
|
|
77
|
-
* @param required - Scopes to check for. Empty means no gate.
|
|
78
|
-
* @param held - The grants held, e.g. `session.scopes`. May be undefined.
|
|
47
|
+
* than enforcing. Fails closed; an empty `required` is satisfied by anything.
|
|
79
48
|
*/
|
|
80
49
|
export const hasScopes = (
|
|
81
50
|
required: readonly string[] | undefined,
|
|
@@ -83,19 +52,9 @@ export const hasScopes = (
|
|
|
83
52
|
): boolean => firstUnsatisfied(required, held) === null
|
|
84
53
|
|
|
85
54
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* Scopes are an AND gate: every entry in `required` must be satisfied. This is
|
|
90
|
-
* deliberately distinct from `permissions`, which OR together — a scope can
|
|
91
|
-
* only ever narrow access, so adding one to a function can never widen it.
|
|
92
|
-
*
|
|
93
|
-
* Fails closed: a session without a `scopes` field, or no session at all,
|
|
94
|
-
* satisfies nothing.
|
|
95
|
-
*
|
|
96
|
-
* @param required - Scopes the function declares. Empty means no gate.
|
|
97
|
-
* @param session - The session to check. May be undefined.
|
|
98
|
-
* @throws {MissingScopeError} Naming the first unsatisfied scope.
|
|
55
|
+
* Throws {@link MissingScopeError} naming the first scope the session does not
|
|
56
|
+
* hold. Fails closed: no session, or a session without `scopes`, satisfies
|
|
57
|
+
* nothing.
|
|
99
58
|
*/
|
|
100
59
|
export const verifyScopes = (
|
|
101
60
|
required: readonly string[] | undefined,
|
|
@@ -19,6 +19,26 @@ export type AIAgentRunnerParams = {
|
|
|
19
19
|
/** Pikku agent function name — forwarded to the LLM proxy (LiteLLM) as
|
|
20
20
|
* request-level metadata so usage can be broken down per agent. */
|
|
21
21
|
agentId?: string
|
|
22
|
+
/**
|
|
23
|
+
* Cancels the model call itself, not just delivery of its output. Set by
|
|
24
|
+
* `streamAIAgent` from the run's interrupt handle so a voice barge-in stops
|
|
25
|
+
* generation upstream rather than leaving tokens being billed into a stream
|
|
26
|
+
* nobody reads. A runner that ignores it degrades to "the caller stops
|
|
27
|
+
* listening", which is the behaviour before this field existed.
|
|
28
|
+
*/
|
|
29
|
+
abortSignal?: AbortSignal
|
|
30
|
+
/**
|
|
31
|
+
* Per-provider settings passed to the model untouched — the escape hatch for
|
|
32
|
+
* anything the shared params above cannot express because only one vendor
|
|
33
|
+
* has it.
|
|
34
|
+
*
|
|
35
|
+
* The setting that motivated it is `reasoningEffort`. A voice turn is heard
|
|
36
|
+
* rather than read, so the wait before the first word is most of the
|
|
37
|
+
* experience: `{ openai: { reasoningEffort: 'minimal' } }` on gpt-5-mini
|
|
38
|
+
* measured 0.9s to first token against 2.5s at the default, and 1.6s of
|
|
39
|
+
* silence is a long time to sit through having just finished speaking.
|
|
40
|
+
*/
|
|
41
|
+
providerOptions?: AIProviderOptions
|
|
22
42
|
}
|
|
23
43
|
|
|
24
44
|
export type AIAgentRunnerResult = {
|
|
@@ -1,31 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* A narrow, dedicated embedding service.
|
|
3
|
-
*
|
|
4
|
-
* Vector stores (Qdrant, Pinecone, Supabase/pgvector, …) depend on this to turn
|
|
5
|
-
* text into vectors, at BOTH index time (ingest) and query time (search). The
|
|
6
|
-
* embedding model is fixed at construction so those two moments cannot drift
|
|
7
|
-
* into different vector spaces — a mismatch would silently break similarity
|
|
8
|
-
* search. Provider addons (e.g. `@pikku/addon-openai`) implement it; the app
|
|
9
|
-
* wires a single instance into `singletonServices.aiEmbedding`.
|
|
10
|
-
*
|
|
11
|
-
* This is deliberately smaller than {@link AIAgentRunnerService} (whose optional
|
|
12
|
-
* `embed`/`embedMany` take a per-call model): a vector store should not have to
|
|
13
|
-
* pull in the whole agent-runner tool loop just to embed, and pinning the model
|
|
14
|
-
* to the service is what guarantees index/query consistency.
|
|
15
|
-
*
|
|
16
|
-
* Documents (ingested corpus) and queries (search text) are embedded through
|
|
17
|
-
* separate methods because some models are asymmetric — Cohere's `input_type`,
|
|
18
|
-
* E5's `query:`/`passage:` prefixes, BGE's query instruction — and must know
|
|
19
|
-
* which side they are embedding to produce comparable vectors. Symmetric
|
|
20
|
-
* providers (e.g. OpenAI) point both methods at the same call.
|
|
21
|
-
*/
|
|
1
|
+
// knowledge: decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md
|
|
22
2
|
export interface AIEmbeddingService {
|
|
23
|
-
/** The embedding model backing this service. Index and query share it. */
|
|
24
3
|
readonly model: string
|
|
25
|
-
/** The vector dimensionality this model produces, when known. */
|
|
26
4
|
readonly dimensions?: number
|
|
27
|
-
/**
|
|
5
|
+
/** Index time. Preserves input order. */
|
|
28
6
|
embedDocuments(values: string[]): Promise<number[][]>
|
|
29
|
-
/**
|
|
7
|
+
/** Query time. */
|
|
30
8
|
embedQuery(value: string): Promise<number[]>
|
|
31
9
|
}
|
|
@@ -76,8 +76,7 @@ class DisabledInvocationAudit implements AuditLog {
|
|
|
76
76
|
async write(_event: AuditLogWriteInput): Promise<void> {
|
|
77
77
|
if (!this.warned) {
|
|
78
78
|
this.warned = true
|
|
79
|
-
//
|
|
80
|
-
// a dropped audit write must never be invisible.
|
|
79
|
+
// knowledge: decisions/security/a-dropped-audit-write-is-always-logged.md
|
|
81
80
|
const logger = (this.wire as any).logger ?? this.logger
|
|
82
81
|
logger?.warn?.(
|
|
83
82
|
`audit.write() dropped for '${this.wire.functionId ?? 'unknown function'}' — the function has no audit config (set audit: true on it)`
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Arguments for signing a content key into a time-limited URL.
|
|
3
|
-
*/
|
|
4
1
|
export interface SignContentKeyArgs<TBucket extends string = string> {
|
|
5
2
|
bucket: TBucket
|
|
6
3
|
contentKey: string
|
|
@@ -8,18 +5,12 @@ export interface SignContentKeyArgs<TBucket extends string = string> {
|
|
|
8
5
|
dateGreaterThan?: Date
|
|
9
6
|
}
|
|
10
7
|
|
|
11
|
-
/**
|
|
12
|
-
* Arguments for signing an arbitrary URL.
|
|
13
|
-
*/
|
|
14
8
|
export interface SignURLArgs {
|
|
15
9
|
url: string
|
|
16
10
|
dateLessThan: Date
|
|
17
11
|
dateGreaterThan?: Date
|
|
18
12
|
}
|
|
19
13
|
|
|
20
|
-
/**
|
|
21
|
-
* Arguments for minting a presigned upload URL.
|
|
22
|
-
*/
|
|
23
14
|
export interface GetUploadURLArgs<TBucket extends string = string> {
|
|
24
15
|
bucket: TBucket
|
|
25
16
|
fileKey: string
|
|
@@ -28,9 +19,6 @@ export interface GetUploadURLArgs<TBucket extends string = string> {
|
|
|
28
19
|
visibility?: 'private' | 'public'
|
|
29
20
|
}
|
|
30
21
|
|
|
31
|
-
/**
|
|
32
|
-
* Result of minting a presigned upload URL.
|
|
33
|
-
*/
|
|
34
22
|
export interface UploadURLResult {
|
|
35
23
|
uploadUrl: string
|
|
36
24
|
assetKey: string
|
|
@@ -38,26 +26,17 @@ export interface UploadURLResult {
|
|
|
38
26
|
uploadMethod?: 'PUT' | 'POST'
|
|
39
27
|
}
|
|
40
28
|
|
|
41
|
-
/**
|
|
42
|
-
* Arguments for an operation that targets a single object by key.
|
|
43
|
-
*/
|
|
44
29
|
export interface BucketKeyArgs<TBucket extends string = string> {
|
|
45
30
|
bucket: TBucket
|
|
46
31
|
key: string
|
|
47
32
|
}
|
|
48
33
|
|
|
49
|
-
/**
|
|
50
|
-
* Arguments for writing a stream to storage.
|
|
51
|
-
*/
|
|
52
34
|
export interface WriteFileArgs<
|
|
53
35
|
TBucket extends string = string,
|
|
54
36
|
> extends BucketKeyArgs<TBucket> {
|
|
55
37
|
stream: ReadableStream | NodeJS.ReadableStream
|
|
56
38
|
}
|
|
57
39
|
|
|
58
|
-
/**
|
|
59
|
-
* Arguments for copying a local file into storage.
|
|
60
|
-
*/
|
|
61
40
|
export interface CopyFileArgs<
|
|
62
41
|
TBucket extends string = string,
|
|
63
42
|
> extends BucketKeyArgs<TBucket> {
|
|
@@ -65,46 +44,22 @@ export interface CopyFileArgs<
|
|
|
65
44
|
}
|
|
66
45
|
|
|
67
46
|
export interface ContentService<TBucket extends string = string> {
|
|
68
|
-
/**
|
|
69
|
-
* Signs a content key to generate a secure, time-limited access URL.
|
|
70
|
-
*/
|
|
71
47
|
signContentKey(args: SignContentKeyArgs<TBucket>): Promise<string>
|
|
72
48
|
|
|
73
|
-
/**
|
|
74
|
-
* Signs an arbitrary URL to generate a secure, time-limited access URL.
|
|
75
|
-
*/
|
|
76
49
|
signURL(args: SignURLArgs): Promise<string>
|
|
77
50
|
|
|
78
|
-
/**
|
|
79
|
-
* Generates a signed URL for uploading a file directly to storage.
|
|
80
|
-
* Bucket policy (size limits, MIME allowlist) is enforced by the implementation.
|
|
81
|
-
*/
|
|
51
|
+
/** Bucket policy (size limits, MIME allowlist) is enforced by the implementation, not the caller. */
|
|
82
52
|
getUploadURL(args: GetUploadURLArgs<TBucket>): Promise<UploadURLResult>
|
|
83
53
|
|
|
84
|
-
/**
|
|
85
|
-
* Deletes a file from the storage backend.
|
|
86
|
-
*/
|
|
87
54
|
deleteFile(args: BucketKeyArgs<TBucket>): Promise<boolean>
|
|
88
55
|
|
|
89
|
-
/**
|
|
90
|
-
* Uploads a file stream to storage under the specified bucket + key.
|
|
91
|
-
*/
|
|
92
56
|
writeFile(args: WriteFileArgs<TBucket>): Promise<boolean>
|
|
93
57
|
|
|
94
|
-
/**
|
|
95
|
-
* Copies a file from a local absolute path into storage.
|
|
96
|
-
*/
|
|
97
58
|
copyFile(args: CopyFileArgs<TBucket>): Promise<boolean>
|
|
98
59
|
|
|
99
|
-
/**
|
|
100
|
-
* Reads a file from storage as a readable stream.
|
|
101
|
-
*/
|
|
102
60
|
readFile(
|
|
103
61
|
args: BucketKeyArgs<TBucket>
|
|
104
62
|
): Promise<ReadableStream | NodeJS.ReadableStream>
|
|
105
63
|
|
|
106
|
-
/**
|
|
107
|
-
* Reads an entire file from storage into a Buffer.
|
|
108
|
-
*/
|
|
109
64
|
readFileAsBuffer(args: BucketKeyArgs<TBucket>): Promise<Buffer>
|
|
110
65
|
}
|