@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
|
@@ -5,8 +5,9 @@ import { createScenarioRunner } from './pikku-scenario-service.js'
|
|
|
5
5
|
import type { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js'
|
|
6
6
|
import { pikkuState, resetPikkuState } from '../../pikku-state.js'
|
|
7
7
|
import { addFunction } from '../../function/function-runner.js'
|
|
8
|
-
import type {
|
|
8
|
+
import type { ScenarioPersona } from '../../services/personas-service.js'
|
|
9
9
|
import type { PikkuWire } from '../../types/core.types.js'
|
|
10
|
+
import type { ScenarioSurface } from './scenario-step.types.js'
|
|
10
11
|
import { requireActor, requireScenarioEnv } from './scenario-step-guards.js'
|
|
11
12
|
|
|
12
13
|
const noopLogger = { error() {}, info() {}, warn() {}, debug() {} }
|
|
@@ -14,7 +15,7 @@ const noopLogger = { error() {}, info() {}, warn() {}, debug() {} }
|
|
|
14
15
|
const fakeActor = (
|
|
15
16
|
name: string,
|
|
16
17
|
handler: (rpcName: string, data: unknown) => Promise<unknown>
|
|
17
|
-
):
|
|
18
|
+
): ScenarioPersona & { calls: Array<{ rpcName: string; data: unknown }> } => {
|
|
18
19
|
const calls: Array<{ rpcName: string; data: unknown }> = []
|
|
19
20
|
return {
|
|
20
21
|
name,
|
|
@@ -87,8 +88,6 @@ describe('scenario actor steps (workflow.do with `actor`)', () => {
|
|
|
87
88
|
const first = await wire.do('step', 'someRpc', {}, { actor: yasser })
|
|
88
89
|
assert.deepEqual(first, { n: 1 })
|
|
89
90
|
|
|
90
|
-
// Simulate replay: reset per-run ordinals so the same logical step name
|
|
91
|
-
// resolves to the same durable step key.
|
|
92
91
|
await (ws as any).beginReplay(runId)
|
|
93
92
|
const replayWire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
94
93
|
const replayed = await replayWire.do(
|
|
@@ -113,7 +112,6 @@ describe('scenario actor steps (workflow.do with `actor`)', () => {
|
|
|
113
112
|
},
|
|
114
113
|
},
|
|
115
114
|
})
|
|
116
|
-
// Function meta says this RPC would normally dispatch via the queue.
|
|
117
115
|
pikkuState(null, 'function', 'meta').queuedRpc = {
|
|
118
116
|
pikkuFuncId: 'queuedRpc',
|
|
119
117
|
workflowQueued: true,
|
|
@@ -146,13 +144,11 @@ const registerStep = (
|
|
|
146
144
|
name: string,
|
|
147
145
|
config: {
|
|
148
146
|
description?: string
|
|
149
|
-
|
|
147
|
+
surfaces?: ScenarioSurface[]
|
|
150
148
|
func: (services: any, data: any, wire: PikkuWire) => Promise<unknown>
|
|
151
149
|
}
|
|
152
150
|
) => {
|
|
153
151
|
addFunction(name, config as any)
|
|
154
|
-
// `pikkuScenarioStep` maps to PikkuFunctionSessionless, which is what the
|
|
155
|
-
// inspector records — a step is driven by an actor, not by a wire session.
|
|
156
152
|
pikkuState(null, 'function', 'meta')[name] = {
|
|
157
153
|
pikkuFuncId: name,
|
|
158
154
|
sessionless: true,
|
|
@@ -306,9 +302,10 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
|
|
|
306
302
|
|
|
307
303
|
test('a browser step fails loudly when no provider is registered', async () => {
|
|
308
304
|
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
305
|
+
scenarioService.setRunSurface('browser')
|
|
309
306
|
const shopper = fakeActor('shopper', async () => ({}))
|
|
310
307
|
registerStep('visitsCheckout', {
|
|
311
|
-
|
|
308
|
+
surfaces: ['browser'],
|
|
312
309
|
func: async () => null,
|
|
313
310
|
})
|
|
314
311
|
|
|
@@ -325,6 +322,7 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
|
|
|
325
322
|
|
|
326
323
|
test('a registered provider hands the step a session keyed by the actor', async () => {
|
|
327
324
|
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
325
|
+
scenarioService.setRunSurface('browser')
|
|
328
326
|
const shopper = fakeActor('shopper', async () => ({}))
|
|
329
327
|
const requested: string[] = []
|
|
330
328
|
const session = { actor: 'shopper' } as any
|
|
@@ -337,7 +335,7 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
|
|
|
337
335
|
|
|
338
336
|
let handed: unknown
|
|
339
337
|
registerStep('visitsCheckout', {
|
|
340
|
-
|
|
338
|
+
surfaces: ['browser'],
|
|
341
339
|
func: async (_services, _data, wire) => {
|
|
342
340
|
handed = wire.browser
|
|
343
341
|
return null
|
|
@@ -354,6 +352,157 @@ describe('pikkuScenarioStep (scenario.step/given/when/then)', () => {
|
|
|
354
352
|
assert.equal(handed, session)
|
|
355
353
|
})
|
|
356
354
|
|
|
355
|
+
test('an action step falls back to its default binding rather than failing', async () => {
|
|
356
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
357
|
+
scenarioService.setRunSurface('browser')
|
|
358
|
+
const ran: ScenarioSurface[] = []
|
|
359
|
+
registerStep('seedsAnAccount', {
|
|
360
|
+
surfaces: ['default'],
|
|
361
|
+
func: async (_services, _data, wire) => {
|
|
362
|
+
ran.push(wire.scenarioStep!.surface)
|
|
363
|
+
return null
|
|
364
|
+
},
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
const runId = await setup(ws)
|
|
368
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
369
|
+
await wire.given('an account exists', 'seedsAnAccount')
|
|
370
|
+
|
|
371
|
+
assert.deepEqual(ran, ['default'], 'setup does not need a UI to be honest')
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
test('an action step with no runnable binding fails rather than silently skipping', async () => {
|
|
375
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
376
|
+
scenarioService.setRunSurface('cli')
|
|
377
|
+
registerStep('clicksBuy', {
|
|
378
|
+
surfaces: ['browser'],
|
|
379
|
+
func: async () => null,
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
const runId = await setup(ws)
|
|
383
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
384
|
+
|
|
385
|
+
await assert.rejects(
|
|
386
|
+
wire.when('shopper buys it', 'clicksBuy'),
|
|
387
|
+
/declares no binding for 'cli'/
|
|
388
|
+
)
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
test('a then step runs every witness, surface first', async () => {
|
|
392
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
393
|
+
scenarioService.setRunSurface('browser')
|
|
394
|
+
scenarioService.setScenarioBrowserProvider({
|
|
395
|
+
sessionFor: async () => ({ actor: 'shopper' }) as any,
|
|
396
|
+
} as any)
|
|
397
|
+
const shopper = fakeActor('shopper', async () => ({}))
|
|
398
|
+
const ran: ScenarioSurface[] = []
|
|
399
|
+
registerStep('seesTheOrderConfirmed', {
|
|
400
|
+
surfaces: ['browser', 'default'],
|
|
401
|
+
func: async (_services, _data, wire) => {
|
|
402
|
+
ran.push(wire.scenarioStep!.surface)
|
|
403
|
+
return { status: 'paid' }
|
|
404
|
+
},
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
const runId = await setup(ws)
|
|
408
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
409
|
+
await wire.then(
|
|
410
|
+
'shopper sees the order confirmed',
|
|
411
|
+
'seesTheOrderConfirmed',
|
|
412
|
+
undefined,
|
|
413
|
+
{ actor: shopper }
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
assert.deepEqual(ran, ['browser', 'default'])
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
test('the page saying something else than the database is a failure', async () => {
|
|
420
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
421
|
+
scenarioService.setRunSurface('browser')
|
|
422
|
+
scenarioService.setScenarioBrowserProvider({
|
|
423
|
+
sessionFor: async () => ({ actor: 'shopper' }) as any,
|
|
424
|
+
} as any)
|
|
425
|
+
const shopper = fakeActor('shopper', async () => ({}))
|
|
426
|
+
registerStep('seesTheOrderConfirmed', {
|
|
427
|
+
surfaces: ['browser', 'default'],
|
|
428
|
+
func: async (_services, _data, wire) =>
|
|
429
|
+
wire.scenarioStep!.surface === 'browser'
|
|
430
|
+
? { status: 'pending' }
|
|
431
|
+
: { status: 'paid' },
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
const runId = await setup(ws)
|
|
435
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
436
|
+
|
|
437
|
+
await assert.rejects(
|
|
438
|
+
wire.then(
|
|
439
|
+
'shopper sees the order confirmed',
|
|
440
|
+
'seesTheOrderConfirmed',
|
|
441
|
+
undefined,
|
|
442
|
+
{ actor: shopper }
|
|
443
|
+
),
|
|
444
|
+
/observed different things on different surfaces/
|
|
445
|
+
)
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
test('a default run pays for only one witness', async () => {
|
|
449
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
450
|
+
const ran: ScenarioSurface[] = []
|
|
451
|
+
registerStep('seesTheOrderConfirmed', {
|
|
452
|
+
surfaces: ['browser', 'default'],
|
|
453
|
+
func: async (_services, _data, wire) => {
|
|
454
|
+
ran.push(wire.scenarioStep!.surface)
|
|
455
|
+
return { status: 'paid' }
|
|
456
|
+
},
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
const runId = await setup(ws)
|
|
460
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
461
|
+
await wire.then('shopper sees the order confirmed', 'seesTheOrderConfirmed')
|
|
462
|
+
|
|
463
|
+
assert.deepEqual(ran, ['default'])
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
test('an assertion with no witness for the run fails instead of passing having checked nothing', async () => {
|
|
467
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
468
|
+
scenarioService.setRunSurface('cli')
|
|
469
|
+
let ran = 0
|
|
470
|
+
registerStep('seesTheBanner', {
|
|
471
|
+
surfaces: ['browser'],
|
|
472
|
+
func: async () => {
|
|
473
|
+
ran++
|
|
474
|
+
return { visible: true }
|
|
475
|
+
},
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
const runId = await setup(ws)
|
|
479
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
480
|
+
|
|
481
|
+
await assert.rejects(
|
|
482
|
+
wire.then('shopper sees the banner', 'seesTheBanner'),
|
|
483
|
+
/has no witness to run on 'cli'/
|
|
484
|
+
)
|
|
485
|
+
assert.equal(ran, 0, 'nothing ran — which is exactly why it must not pass')
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
test('a browser-only assertion is not silently skipped by the fast suite', async () => {
|
|
489
|
+
// The fast path is where this is most dangerous: `--run default` prints no
|
|
490
|
+
// coverage line, so a skipped assertion would leave no trace at all.
|
|
491
|
+
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
492
|
+
registerStep('seesTheBanner', {
|
|
493
|
+
surfaces: ['browser'],
|
|
494
|
+
func: async () => ({ visible: true }),
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
const runId = await setup(ws)
|
|
498
|
+
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
499
|
+
|
|
500
|
+
await assert.rejects(
|
|
501
|
+
wire.then('shopper sees the banner', 'seesTheBanner'),
|
|
502
|
+
/has no witness to run on 'default'/
|
|
503
|
+
)
|
|
504
|
+
})
|
|
505
|
+
|
|
357
506
|
test('a non-string step target is rejected instead of silently dispatching', async () => {
|
|
358
507
|
const { workflowService: ws, scenarioService } = createScenarioRunner()
|
|
359
508
|
const runId = await setup(ws)
|
|
@@ -446,8 +595,6 @@ describe('scenario step input is recorded on the run', () => {
|
|
|
446
595
|
packageName: '@pikku/addon-todos',
|
|
447
596
|
})
|
|
448
597
|
|
|
449
|
-
// A reporter renders each step's prose from this, so two calls to one step
|
|
450
|
-
// must be distinguishable by what they were asked to check.
|
|
451
598
|
const steps = await ws.getRunSteps(runId)
|
|
452
599
|
assert.deepEqual(
|
|
453
600
|
steps.map((step) => step.data),
|
|
@@ -496,8 +643,6 @@ describe('scenario step names its function on the run', () => {
|
|
|
496
643
|
|
|
497
644
|
const runId = await setup(ws)
|
|
498
645
|
const wire = ws.createWorkflowWire('scenarioTest', runId, {})
|
|
499
|
-
// What a loop produces: the durable name is the interpolated one, so it
|
|
500
|
-
// matches no statically recorded step name.
|
|
501
646
|
for (const packageName of ['console', 'todos']) {
|
|
502
647
|
await wire.then(`sees ${packageName}`, 'seesAddon', { packageName })
|
|
503
648
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ScenarioPersona } from '../../services/personas-service.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Scenario steps: named, typed units of scenario behaviour.
|
|
@@ -14,6 +14,77 @@ import type { ScenarioActor } from '../../services/scenario-actors-service.js'
|
|
|
14
14
|
*/
|
|
15
15
|
export type ScenarioStepPhase = 'step' | 'given' | 'when' | 'then'
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Who acts in a step.
|
|
19
|
+
*
|
|
20
|
+
* `persona` is a person driving the system through one of its surfaces — the
|
|
21
|
+
* ordinary `pikkuScenarioStep`. `platform` is the app acting on itself ("the
|
|
22
|
+
* platform has expired the trial"), and `addon` is a third-party system acting
|
|
23
|
+
* on it ("Stripe's webhook arrives"), contributed by the addon that wraps that
|
|
24
|
+
* service.
|
|
25
|
+
*
|
|
26
|
+
* The three are separate declarations rather than a field on one, so the
|
|
27
|
+
* inspector verifies a step's kind by which function was called rather than by
|
|
28
|
+
* trusting a string literal — and so an addon package exports only addon steps,
|
|
29
|
+
* which is checkable.
|
|
30
|
+
*/
|
|
31
|
+
export type ScenarioStepKind = 'persona' | 'platform' | 'addon'
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* How an actor drives the system for one step.
|
|
35
|
+
*
|
|
36
|
+
* A step declares one implementation per surface it supports, and the runner
|
|
37
|
+
* picks between them — so the same ladder can run through a real browser, over
|
|
38
|
+
* the websocket, or entirely server-side.
|
|
39
|
+
*
|
|
40
|
+
* `default` is the floor: it is what every other surface falls back to, so it
|
|
41
|
+
* can never itself fall back.
|
|
42
|
+
*/
|
|
43
|
+
export type ScenarioSurface = 'browser' | 'cli' | 'default'
|
|
44
|
+
|
|
45
|
+
export const SCENARIO_SURFACES: readonly ScenarioSurface[] = [
|
|
46
|
+
'browser',
|
|
47
|
+
'cli',
|
|
48
|
+
'default',
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* How a step's declared surfaces resolve for one run.
|
|
53
|
+
*
|
|
54
|
+
* `given`/`when`/`step` bindings are **alternatives** — clicking Buy and calling
|
|
55
|
+
* `createOrder` are two ways to cause one effect, so exactly one runs.
|
|
56
|
+
*
|
|
57
|
+
* `then` bindings are **witnesses** — "the order row says paid" and "the
|
|
58
|
+
* confirmation panel says paid" are different claims that share a name, and the
|
|
59
|
+
* gap between them is the bug nobody catches. So every declared witness runs and
|
|
60
|
+
* they must agree.
|
|
61
|
+
*/
|
|
62
|
+
export type ScenarioSurfaceResolution =
|
|
63
|
+
| {
|
|
64
|
+
kind: 'action'
|
|
65
|
+
surface: ScenarioSurface
|
|
66
|
+
/** The run asked for a surface this step does not implement. */
|
|
67
|
+
fellBack: boolean
|
|
68
|
+
}
|
|
69
|
+
| {
|
|
70
|
+
kind: 'witness'
|
|
71
|
+
/**
|
|
72
|
+
* Every witness to run, surface first. Empty means the assertion has no
|
|
73
|
+
* binding this run can execute at all — nothing would check anything, so
|
|
74
|
+
* the step fails rather than reporting a pass it never earned.
|
|
75
|
+
*/
|
|
76
|
+
surfaces: ScenarioSurface[]
|
|
77
|
+
/**
|
|
78
|
+
* Something checked the assertion, but not on the surface its prose
|
|
79
|
+
* claims — so nobody looked at the UI. Reported as its own state and
|
|
80
|
+
* counted against coverage: not being in the UI *is* the finding.
|
|
81
|
+
*
|
|
82
|
+
* Disjoint from an empty `surfaces`; an assertion that ran nowhere is a
|
|
83
|
+
* failure, not a coverage statistic.
|
|
84
|
+
*/
|
|
85
|
+
unwitnessed: boolean
|
|
86
|
+
}
|
|
87
|
+
|
|
17
88
|
/**
|
|
18
89
|
* Options accepted by `scenario.step/given/when/then`.
|
|
19
90
|
*
|
|
@@ -22,7 +93,7 @@ export type ScenarioStepPhase = 'step' | 'given' | 'when' | 'then'
|
|
|
22
93
|
* default to no retries.
|
|
23
94
|
*/
|
|
24
95
|
export interface ScenarioStepOptions {
|
|
25
|
-
/** The actor this step runs as. Required for steps declaring `browser
|
|
96
|
+
/** The actor this step runs as. Required for steps declaring a `browser` binding. */
|
|
26
97
|
actor?: unknown
|
|
27
98
|
/** Overrides the step's own `description` for this call site only. */
|
|
28
99
|
description?: string
|
|
@@ -33,7 +104,7 @@ export interface ScenarioStepOptions {
|
|
|
33
104
|
|
|
34
105
|
/**
|
|
35
106
|
* The environment a scenario run targets, as declared in pikku.config.json
|
|
36
|
-
* under `
|
|
107
|
+
* under `environments`.
|
|
37
108
|
*/
|
|
38
109
|
export interface ScenarioEnvironment {
|
|
39
110
|
/** Base API URL of the target app, INCLUDING the HTTP prefix. */
|
|
@@ -46,16 +117,21 @@ export interface ScenarioEnvironment {
|
|
|
46
117
|
* The `scenarioStep` wire, present on every scenario step invocation.
|
|
47
118
|
*
|
|
48
119
|
* `TActor` is the project's own actor type, so a step reaches only the RPCs its
|
|
49
|
-
* actors can actually call. It defaults to the open `
|
|
120
|
+
* actors can actually call. It defaults to the open `ScenarioPersona` for a
|
|
50
121
|
* project that declares no registry.
|
|
51
122
|
*/
|
|
52
|
-
export interface PikkuScenarioStepWire<TActor =
|
|
123
|
+
export interface PikkuScenarioStepWire<TActor = ScenarioPersona> {
|
|
53
124
|
/** Registered step name (also its pikkuFuncId) */
|
|
54
125
|
name: string
|
|
55
126
|
/** Durable key within the run; may carry an `#ordinal` suffix when repeated */
|
|
56
127
|
stepName: string
|
|
57
128
|
runId: string
|
|
58
129
|
phase: ScenarioStepPhase
|
|
130
|
+
/**
|
|
131
|
+
* Which of the step's bindings is currently executing. A `then` step runs once
|
|
132
|
+
* per witness, so its body sees this change between invocations.
|
|
133
|
+
*/
|
|
134
|
+
surface: ScenarioSurface
|
|
59
135
|
/**
|
|
60
136
|
* The actor this step runs as, when one was given. Call RPCs through it
|
|
61
137
|
* (`actor.invoke(...)`) so they run against the target environment as that
|
|
@@ -96,7 +172,7 @@ export interface TestIdSelector {
|
|
|
96
172
|
|
|
97
173
|
/**
|
|
98
174
|
* Structural browser handle, present only when the runner provisioned a
|
|
99
|
-
* browser for this step (`browser
|
|
175
|
+
* browser for this step (a `browser` binding on the step config).
|
|
100
176
|
*
|
|
101
177
|
* `@pikku/core` deliberately never imports playwright — it must stay
|
|
102
178
|
* dependency-free for edge runtimes. `@pikku/playwright` augments this
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { resolveScenarioSurfaces, witnessesAgree } from './scenario-surface.js'
|
|
4
|
+
import type { ScenarioSurface } from './scenario-step.types.js'
|
|
5
|
+
|
|
6
|
+
const ALL: ScenarioSurface[] = ['browser', 'cli', 'default']
|
|
7
|
+
|
|
8
|
+
describe('action steps pick exactly one binding', () => {
|
|
9
|
+
test('runs the binding the run asked for', () => {
|
|
10
|
+
assert.deepEqual(resolveScenarioSurfaces('when', ALL, 'browser'), {
|
|
11
|
+
kind: 'action',
|
|
12
|
+
surface: 'browser',
|
|
13
|
+
fellBack: false,
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('falls back to default and says so when the surface is not implemented', () => {
|
|
18
|
+
assert.deepEqual(resolveScenarioSurfaces('when', ['default'], 'browser'), {
|
|
19
|
+
kind: 'action',
|
|
20
|
+
surface: 'default',
|
|
21
|
+
fellBack: true,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('given and step resolve like when, not like then', () => {
|
|
26
|
+
for (const phase of ['given', 'step'] as const) {
|
|
27
|
+
const resolution = resolveScenarioSurfaces(phase, ALL, 'cli')
|
|
28
|
+
assert.equal(resolution.kind, 'action')
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('a default run never counts as a fallback', () => {
|
|
33
|
+
assert.deepEqual(resolveScenarioSurfaces('when', ['default'], 'default'), {
|
|
34
|
+
kind: 'action',
|
|
35
|
+
surface: 'default',
|
|
36
|
+
fellBack: false,
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('then steps run every witness', () => {
|
|
42
|
+
test('a browser run checks the page AND the system of record', () => {
|
|
43
|
+
assert.deepEqual(
|
|
44
|
+
resolveScenarioSurfaces('then', ['browser', 'default'], 'browser'),
|
|
45
|
+
{ kind: 'witness', surfaces: ['browser', 'default'], unwitnessed: false }
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('the surface witness comes first, so its failure is the one reported', () => {
|
|
50
|
+
const resolution = resolveScenarioSurfaces(
|
|
51
|
+
'then',
|
|
52
|
+
['default', 'browser'],
|
|
53
|
+
'browser'
|
|
54
|
+
)
|
|
55
|
+
assert.equal(resolution.kind, 'witness')
|
|
56
|
+
assert.deepEqual(
|
|
57
|
+
resolution.kind === 'witness' ? resolution.surfaces[0] : null,
|
|
58
|
+
'browser'
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test('a default run is unchanged — one witness, no extra cost', () => {
|
|
63
|
+
assert.deepEqual(
|
|
64
|
+
resolveScenarioSurfaces('then', ['browser', 'default'], 'default'),
|
|
65
|
+
{ kind: 'witness', surfaces: ['default'], unwitnessed: false }
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('no witness for the run surface is flagged rather than excused', () => {
|
|
70
|
+
assert.deepEqual(resolveScenarioSurfaces('then', ['default'], 'browser'), {
|
|
71
|
+
kind: 'witness',
|
|
72
|
+
surfaces: ['default'],
|
|
73
|
+
unwitnessed: true,
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('a browser-only assertion has nothing to run on a default run', () => {
|
|
78
|
+
// No witness at all is not a coverage statistic — nothing checked anything,
|
|
79
|
+
// so `unwitnessed` stays false and the caller is expected to fail the step.
|
|
80
|
+
assert.deepEqual(resolveScenarioSurfaces('then', ['browser'], 'default'), {
|
|
81
|
+
kind: 'witness',
|
|
82
|
+
surfaces: [],
|
|
83
|
+
unwitnessed: false,
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('an assertion that runs nowhere is not counted as merely unwitnessed', () => {
|
|
88
|
+
assert.deepEqual(resolveScenarioSurfaces('then', ['browser'], 'cli'), {
|
|
89
|
+
kind: 'witness',
|
|
90
|
+
surfaces: [],
|
|
91
|
+
unwitnessed: false,
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('unwitnessed means checked somewhere else, never checked nowhere', () => {
|
|
96
|
+
const ranElsewhere = resolveScenarioSurfaces('then', ['default'], 'cli')
|
|
97
|
+
assert.equal(ranElsewhere.kind, 'witness')
|
|
98
|
+
assert.ok(
|
|
99
|
+
ranElsewhere.kind === 'witness' && ranElsewhere.surfaces.length > 0,
|
|
100
|
+
'the two states are disjoint: unwitnessed always has something that ran'
|
|
101
|
+
)
|
|
102
|
+
assert.equal(
|
|
103
|
+
ranElsewhere.kind === 'witness' && ranElsewhere.unwitnessed,
|
|
104
|
+
true
|
|
105
|
+
)
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
describe('witness agreement', () => {
|
|
110
|
+
test('key order does not make two observations disagree', () => {
|
|
111
|
+
assert.equal(
|
|
112
|
+
witnessesAgree(
|
|
113
|
+
{ status: 'paid', total: 500 },
|
|
114
|
+
{ total: 500, status: 'paid' }
|
|
115
|
+
),
|
|
116
|
+
true
|
|
117
|
+
)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('a page showing something else is a disagreement', () => {
|
|
121
|
+
assert.equal(
|
|
122
|
+
witnessesAgree({ status: 'paid' }, { status: 'pending' }),
|
|
123
|
+
false
|
|
124
|
+
)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('a witness that asserted by throwing is not compared', () => {
|
|
128
|
+
assert.equal(witnessesAgree(undefined, { status: 'paid' }), true)
|
|
129
|
+
assert.equal(witnessesAgree({ status: 'paid' }, undefined), true)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('nested observations compare structurally', () => {
|
|
133
|
+
assert.equal(
|
|
134
|
+
witnessesAgree(
|
|
135
|
+
{ order: { items: [{ sku: 'a' }, { sku: 'b' }] } },
|
|
136
|
+
{ order: { items: [{ sku: 'a' }, { sku: 'b' }] } }
|
|
137
|
+
),
|
|
138
|
+
true
|
|
139
|
+
)
|
|
140
|
+
assert.equal(
|
|
141
|
+
witnessesAgree({ items: ['a', 'b'] }, { items: ['b', 'a'] }),
|
|
142
|
+
false
|
|
143
|
+
)
|
|
144
|
+
})
|
|
145
|
+
})
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ScenarioStepPhase,
|
|
3
|
+
ScenarioSurface,
|
|
4
|
+
ScenarioSurfaceResolution,
|
|
5
|
+
} from './scenario-step.types.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolve which of a step's declared bindings run, for one step, in one run.
|
|
9
|
+
*
|
|
10
|
+
* The asymmetry between phases is the whole point — see
|
|
11
|
+
* {@link ScenarioSurfaceResolution}.
|
|
12
|
+
*/
|
|
13
|
+
export const resolveScenarioSurfaces = (
|
|
14
|
+
phase: ScenarioStepPhase,
|
|
15
|
+
declared: readonly ScenarioSurface[],
|
|
16
|
+
runSurface: ScenarioSurface
|
|
17
|
+
): ScenarioSurfaceResolution => {
|
|
18
|
+
const has = (surface: ScenarioSurface) => declared.includes(surface)
|
|
19
|
+
|
|
20
|
+
if (phase !== 'then') {
|
|
21
|
+
if (has(runSurface)) {
|
|
22
|
+
return { kind: 'action', surface: runSurface, fellBack: false }
|
|
23
|
+
}
|
|
24
|
+
return { kind: 'action', surface: 'default', fellBack: true }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const surfaces: ScenarioSurface[] = []
|
|
28
|
+
if (runSurface !== 'default' && has(runSurface)) {
|
|
29
|
+
surfaces.push(runSurface)
|
|
30
|
+
}
|
|
31
|
+
if (has('default')) {
|
|
32
|
+
surfaces.push('default')
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
kind: 'witness',
|
|
36
|
+
surfaces,
|
|
37
|
+
// Only meaningful once something ran: an assertion checked server-side
|
|
38
|
+
// under `--run browser` is a coverage gap, but one checked nowhere at all
|
|
39
|
+
// is a step that did not happen, which the caller fails rather than counts.
|
|
40
|
+
unwitnessed:
|
|
41
|
+
surfaces.length > 0 && runSurface !== 'default' && !has(runSurface),
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Structural comparison of two witnesses' observations.
|
|
47
|
+
*
|
|
48
|
+
* A witness that returns `undefined` asserted by throwing rather than by
|
|
49
|
+
* reporting what it saw, so it is not compared — that keeps assertion-style
|
|
50
|
+
* steps working without forcing every one of them to return a value.
|
|
51
|
+
*/
|
|
52
|
+
export const witnessesAgree = (a: unknown, b: unknown): boolean => {
|
|
53
|
+
if (a === undefined || b === undefined) {
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
return stableStringify(a) === stableStringify(b)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const stableStringify = (value: unknown): string => {
|
|
60
|
+
if (value === null || typeof value !== 'object') {
|
|
61
|
+
return JSON.stringify(value) ?? 'undefined'
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
return `[${value.map(stableStringify).join(',')}]`
|
|
65
|
+
}
|
|
66
|
+
const entries = Object.entries(value as Record<string, unknown>)
|
|
67
|
+
.filter(([, v]) => v !== undefined)
|
|
68
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
69
|
+
.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`)
|
|
70
|
+
return `{${entries.join(',')}}`
|
|
71
|
+
}
|
|
@@ -5,8 +5,6 @@ import { InMemoryWorkflowService } from '../../services/in-memory-workflow-servi
|
|
|
5
5
|
import { pikkuState } from '../../pikku-state.js'
|
|
6
6
|
import { WorkflowDispatchException } from './pikku-workflow-service.js'
|
|
7
7
|
|
|
8
|
-
// Register a `workflowQueued: true` function so the workflow's `do()` routes
|
|
9
|
-
// the step through the queue (dispatchStep) instead of running it inline.
|
|
10
8
|
function registerDispatchedFn(rpcName: string): void {
|
|
11
9
|
const funcId = `fn:${rpcName}`
|
|
12
10
|
pikkuState(null, 'rpc', 'meta', { [rpcName]: funcId } as any)
|
|
@@ -31,18 +29,17 @@ describe('dispatch durability: a transient queue failure is recoverable', () =>
|
|
|
31
29
|
} as any)
|
|
32
30
|
|
|
33
31
|
const ws = new InMemoryWorkflowService()
|
|
34
|
-
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
32
|
+
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
33
|
+
type: 'test',
|
|
34
|
+
})
|
|
35
35
|
await ws.insertStepState(runId, 'thing', 'doThing', {})
|
|
36
36
|
|
|
37
|
-
// Queue is down → dispatch throws the TRANSIENT exception (not a step failure).
|
|
38
37
|
await assert.rejects(
|
|
39
38
|
(ws as any).rpcStep(runId, 'thing', 'doThing', {}, {}),
|
|
40
39
|
(err: any) => err instanceof WorkflowDispatchException,
|
|
41
40
|
'a queue outage surfaces as WorkflowDispatchException'
|
|
42
41
|
)
|
|
43
42
|
|
|
44
|
-
// The step must NOT be stranded in `scheduled` — otherwise replay would pause
|
|
45
|
-
// forever on a job that was never enqueued.
|
|
46
43
|
const afterFail = await ws.getStepState(runId, 'thing')
|
|
47
44
|
assert.equal(
|
|
48
45
|
afterFail.status,
|
|
@@ -50,14 +47,13 @@ describe('dispatch durability: a transient queue failure is recoverable', () =>
|
|
|
50
47
|
'step stays pending after a failed dispatch'
|
|
51
48
|
)
|
|
52
49
|
|
|
53
|
-
// The run itself must stay alive (not failed) — it is the snapshot we replay.
|
|
54
50
|
const runAfterFail = await ws.getRun(runId)
|
|
55
|
-
assert.notEqual(
|
|
51
|
+
assert.notEqual(
|
|
52
|
+
runAfterFail?.status,
|
|
53
|
+
'failed',
|
|
54
|
+
'run is not failed by a queue blip'
|
|
55
|
+
)
|
|
56
56
|
|
|
57
|
-
// Queue recovers → replaying the step now dispatches (pauses via async exception)
|
|
58
|
-
// and the step transitions to `scheduled`. A real replay runs through
|
|
59
|
-
// runWorkflowJob which resets the ordinal counter; simulate that so the
|
|
60
|
-
// second reach resolves to the same step key, not the next ordinal.
|
|
61
57
|
await (ws as any).beginReplay(runId)
|
|
62
58
|
queueUp = true
|
|
63
59
|
await assert.rejects(
|
|
@@ -81,7 +77,6 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
|
|
|
81
77
|
logger: silentLogger,
|
|
82
78
|
} as any)
|
|
83
79
|
const ws = new InMemoryWorkflowService()
|
|
84
|
-
// Override the replay to throw whatever the test wants.
|
|
85
80
|
;(ws as any).runWorkflowJob = async () => throwIt()
|
|
86
81
|
return ws
|
|
87
82
|
}
|
|
@@ -90,7 +85,9 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
|
|
|
90
85
|
const ws = makeService(() => {
|
|
91
86
|
throw new WorkflowDispatchException('r', 's')
|
|
92
87
|
})
|
|
93
|
-
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
88
|
+
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
89
|
+
type: 'test',
|
|
90
|
+
})
|
|
94
91
|
|
|
95
92
|
await assert.rejects(
|
|
96
93
|
ws.orchestrateWorkflow(runId, {}),
|
|
@@ -108,7 +105,9 @@ describe('orchestrateWorkflow treats a dispatch failure as non-terminal', () =>
|
|
|
108
105
|
const ws = makeService(() => {
|
|
109
106
|
throw new Error('business logic blew up')
|
|
110
107
|
})
|
|
111
|
-
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
108
|
+
const runId = await ws.createRun('flow', {}, false, 'hash', {
|
|
109
|
+
type: 'test',
|
|
110
|
+
})
|
|
112
111
|
|
|
113
112
|
await assert.rejects(ws.orchestrateWorkflow(runId, {}))
|
|
114
113
|
const run = await ws.getRun(runId)
|