@pikku/core 0.12.142 → 0.12.144
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/analytics.d.ts +14 -0
- package/dist/analytics/analytics.js +14 -0
- package/dist/analytics/analytics.types.d.ts +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +1 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +1 -0
- package/dist/analytics/mint-cookie.d.ts +1 -0
- package/dist/{wirings/channel/channel-middleware-runner.d.ts → channel-middleware-runner.d.ts} +17 -3
- package/dist/{wirings/channel/channel-middleware-runner.js → channel-middleware-runner.js} +24 -8
- package/dist/classification/data-classification.d.ts +13 -0
- package/dist/classification/secret-value.d.ts +7 -0
- package/dist/classification/secret-value.js +7 -0
- package/dist/crypto-utils.d.ts +93 -0
- package/dist/crypto-utils.js +92 -0
- package/dist/dev/hot-reload.d.ts +16 -0
- package/dist/dev/hot-reload.js +16 -1
- package/dist/dev/module-runner.js +7 -3
- package/dist/dev/reload-meta.js +1 -1
- package/dist/errors/error-handler.d.ts +9 -0
- package/dist/errors/error-handler.js +8 -0
- package/dist/errors/errors.d.ts +219 -0
- package/dist/errors/errors.js +227 -0
- package/dist/errors/serialized-error.d.ts +4 -0
- package/dist/function/abort-scope.d.ts +5 -0
- package/dist/function/function-meta.types.d.ts +20 -0
- package/dist/function/function-runner.d.ts +41 -0
- package/dist/function/function-runner.js +57 -11
- package/dist/function/functions.types.d.ts +59 -0
- package/dist/function/functions.types.js +23 -0
- package/dist/function/list.types.d.ts +4 -0
- package/dist/lifecycle.d.ts +12 -1
- package/dist/lifecycle.js +12 -1
- package/dist/middleware/addon-scope-cap.d.ts +4 -0
- package/dist/middleware/addon-scope-cap.js +7 -3
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.js +5 -13
- package/dist/middleware/auth-cookie.js +3 -3
- package/dist/middleware/middleware-factories.d.ts +17 -0
- package/dist/middleware/middleware-factories.js +17 -0
- package/dist/middleware/middleware.types.d.ts +23 -0
- package/dist/middleware/remote-auth.d.ts +15 -0
- package/dist/middleware/remote-auth.js +18 -3
- package/dist/middleware/remote-jobs-secret.js +2 -10
- package/dist/middleware-runner.d.ts +7 -0
- package/dist/middleware-runner.js +23 -7
- package/dist/permissions.d.ts +13 -0
- package/dist/permissions.js +13 -0
- package/dist/pikku-state.d.ts +49 -0
- package/dist/pikku-state.js +49 -0
- package/dist/remote.js +20 -5
- package/dist/schema.d.ts +36 -0
- package/dist/schema.js +36 -0
- package/dist/services/agent-run-state-service.d.ts +8 -0
- package/dist/services/agent-runner-service.d.ts +24 -0
- package/dist/services/agent-storage-service.d.ts +8 -0
- package/dist/services/ai-embedding-service.d.ts +4 -0
- package/dist/services/audit-service.d.ts +48 -0
- package/dist/services/audit-service.js +22 -0
- package/dist/services/content-service.d.ts +34 -0
- package/dist/services/credential-wire-service.d.ts +9 -0
- package/dist/services/credential-wire-service.js +9 -0
- package/dist/services/deployment-service.d.ts +14 -0
- package/dist/services/email-service.d.ts +20 -0
- package/dist/services/email-template.d.ts +24 -0
- package/dist/services/email-template.js +12 -0
- package/dist/services/file-scenario-run-store.d.ts +5 -0
- package/dist/services/file-scenario-run-store.js +4 -0
- package/dist/services/gateway-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.d.ts +5 -0
- package/dist/services/in-memory-agent-run-state-service.js +5 -0
- package/dist/services/in-memory-lease-service.d.ts +5 -0
- package/dist/services/in-memory-lease-service.js +5 -0
- package/dist/services/in-memory-session-store.d.ts +4 -0
- package/dist/services/in-memory-session-store.js +4 -0
- package/dist/services/incoming-webhook-queue.d.ts +2 -0
- package/dist/services/incoming-webhook-queue.js +2 -0
- package/dist/services/incoming-webhook-service.d.ts +11 -1
- package/dist/services/incoming-webhook-service.js +5 -1
- package/dist/services/index.d.ts +1 -5
- package/dist/services/index.js +1 -5
- package/dist/services/jwt-service.d.ts +8 -0
- package/dist/services/lease-service.d.ts +5 -0
- package/dist/services/lease-service.js +1 -0
- package/dist/services/local-content-request-handler.d.ts +20 -0
- package/dist/services/local-content-request-handler.js +11 -0
- package/dist/services/local-content.d.ts +45 -0
- package/dist/services/local-content.js +35 -0
- package/dist/services/local-credential-service.d.ts +5 -0
- package/dist/services/local-credential-service.js +5 -0
- package/dist/services/local-email-service.d.ts +7 -0
- package/dist/services/local-email-service.js +7 -0
- package/dist/services/local-secrets.d.ts +8 -0
- package/dist/services/local-secrets.js +8 -0
- package/dist/services/local-variables.d.ts +6 -0
- package/dist/services/local-variables.js +6 -0
- package/dist/services/logger.d.ts +4 -0
- package/dist/services/logger.js +4 -0
- package/dist/services/meta-service.d.ts +38 -0
- package/dist/services/meta-service.js +6 -0
- package/dist/services/queue-webhook-service.d.ts +19 -0
- package/dist/services/queue-webhook-service.js +19 -0
- package/dist/services/remote-jobs.d.ts +8 -13
- package/dist/services/remote-jobs.js +3 -54
- package/dist/services/scenario-cookie-jar.d.ts +4 -0
- package/dist/services/scheduler-service.d.ts +16 -0
- package/dist/services/scheduler-service.js +12 -0
- package/dist/services/schema-service.d.ts +9 -0
- package/dist/services/scope-service.d.ts +10 -0
- package/dist/services/scoped-secret-service.d.ts +5 -0
- package/dist/services/scoped-secret-service.js +5 -0
- package/dist/services/secret-host-binding.d.ts +5 -0
- package/dist/services/secret-host-binding.js +5 -0
- package/dist/services/secret-service.d.ts +19 -1
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +6 -0
- package/dist/services/session-store.d.ts +5 -0
- package/dist/services/stub-tracker.d.ts +1 -0
- package/dist/services/temporary-file-service.d.ts +9 -0
- package/dist/services/temporary-file-service.js +9 -0
- package/dist/services/trigger-service.d.ts +4 -0
- package/dist/services/trigger-source-store.d.ts +13 -0
- package/dist/services/trigger-source-store.js +7 -0
- package/dist/services/typed-credential-service.d.ts +6 -0
- package/dist/services/typed-credential-service.js +5 -0
- package/dist/services/typed-secret-service.d.ts +12 -0
- package/dist/services/typed-secret-service.js +11 -0
- package/dist/services/typed-variables-service.d.ts +1 -0
- package/dist/services/user-session-service.d.ts +31 -1
- package/dist/services/user-session-service.js +29 -3
- package/dist/services/v8-coverage-service.d.ts +27 -0
- package/dist/services/v8-coverage-service.js +5 -0
- package/dist/services/variables-service.d.ts +8 -0
- package/dist/services/virtual-user-sign-in.d.ts +1 -0
- package/dist/services/virtual-user-statement.d.ts +8 -0
- package/dist/services/virtual-user-statement.js +4 -0
- package/dist/services/webhook-service.d.ts +25 -0
- package/dist/services/webhook-service.js +15 -0
- package/dist/services/workflow-service.d.ts +6 -0
- package/dist/test-utils.js +1 -1
- package/dist/testing/service-tests.d.ts +4 -0
- package/dist/time-utils.d.ts +15 -0
- package/dist/time-utils.js +14 -0
- package/dist/types/core.types.d.ts +80 -0
- package/dist/types/state.types.d.ts +4 -0
- package/dist/utils/hmac.d.ts +3 -0
- package/dist/utils/safe-fetch.d.ts +14 -0
- package/dist/utils/safe-fetch.js +13 -0
- package/dist/utils/stable-stringify.d.ts +11 -0
- package/dist/utils/stable-stringify.js +33 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +22 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +7 -0
- package/dist/wirings/addon/define-screens.d.ts +2 -0
- package/dist/wirings/addon/remote-addon-auth.d.ts +9 -0
- package/dist/wirings/addon/remote-addon-auth.js +5 -0
- package/dist/wirings/addon/wire-addon.d.ts +4 -0
- package/dist/wirings/addon/wire-remote-addon.d.ts +1 -0
- package/dist/wirings/agent/agent-agui.d.ts +14 -5
- package/dist/wirings/agent/agent-agui.js +17 -6
- package/dist/wirings/agent/agent-helpers.d.ts +61 -1
- package/dist/wirings/agent/agent-helpers.js +62 -2
- package/dist/wirings/agent/agent-interrupt.d.ts +5 -0
- package/dist/wirings/agent/agent-output.d.ts +20 -0
- package/dist/wirings/agent/agent-output.js +69 -0
- package/dist/wirings/agent/agent-prepare.d.ts +41 -0
- package/dist/wirings/agent/agent-prepare.js +38 -2
- package/dist/wirings/agent/agent-registry.d.ts +8 -0
- package/dist/wirings/agent/agent-registry.js +10 -4
- package/dist/wirings/agent/agent-runner.d.ts +33 -0
- package/dist/wirings/agent/agent-runner.js +40 -7
- package/dist/wirings/agent/agent-stream.d.ts +30 -0
- package/dist/wirings/agent/agent-stream.js +33 -11
- package/dist/wirings/agent/agent.types.d.ts +43 -0
- package/dist/wirings/agent/voice-input.d.ts +12 -0
- package/dist/wirings/agent/voice-input.js +12 -0
- package/dist/wirings/agent/voice-output.d.ts +14 -0
- package/dist/wirings/agent/voice-output.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.js +1 -2
- package/dist/wirings/agent-scorer/agent-scorer-registry.d.ts +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.js +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.d.ts +1 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.js +1 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +7 -0
- package/dist/wirings/channel/channel-common.js +1 -1
- package/dist/wirings/channel/channel-rpc.types.d.ts +5 -0
- package/dist/wirings/channel/channel-runner.d.ts +22 -0
- package/dist/wirings/channel/channel-runner.js +22 -0
- package/dist/wirings/channel/channel-store.d.ts +8 -0
- package/dist/wirings/channel/channel-store.js +7 -0
- package/dist/wirings/channel/channel.types.d.ts +18 -0
- package/dist/wirings/channel/define-channel-routes.d.ts +5 -0
- package/dist/wirings/channel/define-channel-routes.js +5 -0
- package/dist/wirings/channel/eventhub-service.d.ts +9 -0
- package/dist/wirings/channel/eventhub-store.d.ts +1 -0
- package/dist/wirings/channel/eventhub-store.js +1 -0
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/index.js +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -0
- package/dist/wirings/channel/local/local-channel-handler.js +1 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +13 -0
- package/dist/wirings/channel/local/local-channel-runner.js +13 -0
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +1 -0
- package/dist/wirings/channel/local/local-eventhub-service.js +1 -0
- package/dist/wirings/channel/log-channels.d.ts +1 -0
- package/dist/wirings/channel/log-channels.js +1 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +5 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +5 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +32 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +31 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +8 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +8 -0
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +43 -0
- package/dist/wirings/cli/cli-runner.js +43 -0
- package/dist/wirings/cli/command-parser.d.ts +13 -0
- package/dist/wirings/cli/command-parser.js +12 -0
- package/dist/wirings/credential/credential-overrides.d.ts +1 -0
- package/dist/wirings/credential/credential.types.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.d.ts +7 -0
- package/dist/wirings/credential/validate-credential-definitions.js +7 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +1 -0
- package/dist/wirings/flag/flag.types.d.ts +3 -0
- package/dist/wirings/gateway/gateway-runner.d.ts +23 -0
- package/dist/wirings/gateway/gateway-runner.js +23 -0
- package/dist/wirings/gateway/gateway.types.d.ts +3 -0
- package/dist/wirings/gateway/local-gateway-service.d.ts +10 -0
- package/dist/{services → wirings/gateway}/local-gateway-service.js +6 -2
- package/dist/wirings/http/http-routes.d.ts +21 -0
- package/dist/wirings/http/http-routes.js +11 -0
- package/dist/wirings/http/http-runner.d.ts +71 -0
- package/dist/wirings/http/http-runner.js +73 -5
- package/dist/wirings/http/http.types.d.ts +27 -0
- package/dist/wirings/http/index.d.ts +1 -0
- package/dist/wirings/http/index.js +1 -0
- package/dist/wirings/http/log-http-routes.d.ts +1 -0
- package/dist/wirings/http/log-http-routes.js +1 -0
- package/dist/wirings/http/merge-request-data.d.ts +12 -0
- package/dist/wirings/http/merge-request-data.js +42 -0
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.js +3 -32
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +1 -0
- package/dist/wirings/http/routers/http-router.d.ts +6 -0
- package/dist/wirings/http/routers/http-router.js +6 -0
- package/dist/wirings/http/web-request.d.ts +17 -0
- package/dist/wirings/http/web-request.js +17 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +7 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.js +7 -0
- package/dist/wirings/mcp/mcp-runner.d.ts +63 -0
- package/dist/wirings/mcp/mcp-runner.js +62 -0
- package/dist/wirings/mcp/mcp.types.d.ts +12 -0
- package/dist/wirings/node/node.types.d.ts +4 -0
- package/dist/wirings/oauth2/oauth2.types.d.ts +2 -0
- package/dist/wirings/queue/in-memory-queue-service.d.ts +23 -0
- package/dist/wirings/queue/in-memory-queue-service.js +129 -0
- package/dist/wirings/queue/index.d.ts +2 -1
- package/dist/wirings/queue/index.js +1 -0
- package/dist/wirings/queue/queue-identity.js +2 -14
- package/dist/wirings/queue/queue-runner.d.ts +37 -0
- package/dist/wirings/queue/queue-runner.js +37 -0
- package/dist/wirings/queue/queue.types.d.ts +56 -0
- package/dist/wirings/queue/register-queue-helper.d.ts +12 -0
- package/dist/wirings/queue/register-queue-helper.js +11 -0
- package/dist/wirings/queue/remote-queue-job.d.ts +11 -0
- package/dist/wirings/queue/remote-queue-job.js +41 -0
- package/dist/wirings/queue/signed-queue-service.d.ts +4 -1
- package/dist/wirings/queue/signed-queue-service.js +3 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -0
- package/dist/wirings/role/role.types.d.ts +3 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +24 -0
- package/dist/wirings/rpc/rpc-runner.js +37 -2
- package/dist/wirings/rpc/rpc-types.d.ts +2 -0
- package/dist/wirings/scheduler/index.d.ts +2 -1
- package/dist/wirings/scheduler/index.js +1 -0
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -0
- package/dist/wirings/scheduler/log-schedulers.js +1 -0
- package/dist/wirings/scheduler/remote-scheduled-job.d.ts +11 -0
- package/dist/wirings/scheduler/remote-scheduled-job.js +20 -0
- package/dist/wirings/scheduler/scheduler-runner.d.ts +29 -0
- package/dist/wirings/scheduler/scheduler-runner.js +28 -0
- package/dist/wirings/scheduler/scheduler.types.d.ts +15 -0
- package/dist/wirings/scope/scope.types.d.ts +5 -0
- package/dist/wirings/secret/index.d.ts +2 -2
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +26 -1
- package/dist/wirings/secret/secret.types.js +1 -0
- package/dist/wirings/secret/validate-secret-definitions.d.ts +8 -0
- package/dist/wirings/secret/validate-secret-definitions.js +15 -0
- package/dist/wirings/trigger/in-memory-trigger-service.d.ts +11 -0
- package/dist/{services → wirings/trigger}/in-memory-trigger-service.js +10 -3
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +8 -3
- package/dist/wirings/trigger/pikku-trigger-service.js +14 -3
- package/dist/wirings/trigger/trigger-runner.d.ts +27 -2
- package/dist/wirings/trigger/trigger-runner.js +35 -2
- package/dist/wirings/trigger/trigger.types.d.ts +26 -4
- package/dist/wirings/trigger/webhook-source-runner.d.ts +24 -0
- package/dist/wirings/trigger/webhook-source-runner.js +19 -0
- package/dist/wirings/trigger/webhook-source.types.d.ts +12 -2
- package/dist/wirings/trigger/webhook-source.types.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +7 -0
- package/dist/wirings/variable/validate-variable-definitions.js +7 -0
- package/dist/wirings/variable/variable.types.d.ts +7 -0
- package/dist/wirings/virtual-user/conversation/conversation.types.d.ts +5 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +6 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.js +1 -1
- package/dist/{services → wirings/virtual-user}/http-virtual-users.d.ts +4 -3
- package/dist/{services → wirings/virtual-user}/http-virtual-users.js +6 -6
- package/dist/wirings/virtual-user/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.js +1 -1
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +2 -1
- package/dist/wirings/virtual-user/run-virtual-user.js +1 -14
- package/dist/wirings/virtual-user/virtual-user-declaration.types.d.ts +4 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +10 -1
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +5 -0
- package/dist/wirings/virtual-user/virtual-user-schedule.js +1 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +1 -0
- package/dist/wirings/webhook/define-outgoing-webhook.d.ts +20 -0
- package/dist/wirings/webhook/define-outgoing-webhook.js +9 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +8 -4
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +7 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +7 -0
- package/dist/wirings/workflow/feature.d.ts +12 -0
- package/dist/wirings/workflow/feature.js +12 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +5 -0
- package/dist/wirings/workflow/graph/graph-node.js +5 -0
- package/dist/wirings/workflow/graph/template.d.ts +6 -0
- package/dist/wirings/workflow/graph/template.js +5 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +12 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +10 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +11 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +1 -0
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.d.ts +8 -3
- package/dist/{services → wirings/workflow}/in-memory-workflow-service.js +9 -4
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +1 -1
- package/dist/wirings/workflow/pikku-scenario-service.js +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +1 -0
- package/dist/wirings/workflow/pikku-workflow-service.js +1 -0
- package/dist/wirings/workflow/run-timeline.d.ts +21 -0
- package/dist/wirings/workflow/run-timeline.js +15 -7
- package/dist/wirings/workflow/scenario-coverage.d.ts +1 -0
- package/dist/wirings/workflow/scenario-poll.d.ts +1 -0
- package/dist/wirings/workflow/scenario-prose.d.ts +6 -0
- package/dist/wirings/workflow/scenario-prose.js +6 -0
- package/dist/wirings/workflow/scenario-run.types.d.ts +3 -0
- package/dist/wirings/workflow/scenario-step.types.d.ts +1 -0
- package/dist/wirings/workflow/scenario-step.types.js +1 -0
- package/dist/wirings/workflow/scenario-surface.js +1 -13
- package/dist/wirings/workflow/scenario.types.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +6 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +6 -0
- package/dist/wirings/workflow/workflow-constants.d.ts +7 -1
- package/dist/wirings/workflow/workflow-constants.js +10 -1
- package/dist/wirings/workflow/workflow-errors.d.ts +13 -0
- package/dist/wirings/workflow/workflow-errors.js +13 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +4 -0
- package/dist/wirings/workflow/workflow-invocation-id.js +4 -0
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +3 -0
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +1 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +1 -0
- package/dist/wirings/workflow/workflow-status-stream.d.ts +1 -0
- package/dist/wirings/workflow/workflow-unwind-plan.js +2 -7
- package/dist/wirings/workflow/workflow.types.d.ts +40 -0
- package/package.json +26 -9
- package/CHANGELOG.md +0 -6961
- package/dist/services/in-memory-queue-service.d.ts +0 -8
- package/dist/services/in-memory-queue-service.js +0 -54
- package/dist/services/in-memory-trigger-service.d.ts +0 -4
- package/dist/services/local-gateway-service.d.ts +0 -6
- package/dist/utils/hash.d.ts +0 -2
- package/dist/utils/hash.js +0 -23
- package/knowledge/decisions/index.md +0 -19
- package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +0 -29
- package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +0 -29
- package/knowledge/decisions/internals/a-held-run-is-woken-later-not-retried.md +0 -28
- package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-agentrunstate-too.md +0 -22
- package/knowledge/decisions/internals/a-reset-suite-makes-the-dev-seed-the-fixture.md +0 -50
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +0 -20
- package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +0 -21
- package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +0 -22
- package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +0 -28
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +0 -49
- package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +0 -32
- package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +0 -66
- package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +0 -24
- package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +0 -21
- package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +0 -34
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +0 -65
- package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +0 -46
- package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +0 -45
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +0 -26
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +0 -32
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +0 -33
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +0 -28
- package/knowledge/decisions/internals/agent-agui-bridge-obeys-the-client-ordering-contract.md +0 -29
- package/knowledge/decisions/internals/agent-audio-chunks-carry-the-format-the-provider-returned.md +0 -20
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +0 -21
- package/knowledge/decisions/internals/agent-credential-suspensions-hide-the-tool-result.md +0 -26
- package/knowledge/decisions/internals/agent-delegate-and-supervise-hide-different-text.md +0 -26
- package/knowledge/decisions/internals/agent-llm-tool-arguments-have-nulls-stripped.md +0 -23
- package/knowledge/decisions/internals/agent-model-config-stays-a-single-resolution-seam.md +0 -25
- package/knowledge/decisions/internals/agent-onerror-hooks-cannot-change-the-failure.md +0 -22
- package/knowledge/decisions/internals/agent-runner-methods-must-keep-their-receiver.md +0 -22
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +0 -22
- package/knowledge/decisions/internals/agent-stream-persistence-is-best-effort.md +0 -27
- package/knowledge/decisions/internals/agent-sub-agents-inherit-the-parent-context-block.md +0 -26
- package/knowledge/decisions/internals/agent-tool-execute-failures-are-logged-unconditionally.md +0 -25
- package/knowledge/decisions/internals/agent-voice-input-transcribes-audio-parts-in-place.md +0 -22
- package/knowledge/decisions/internals/agent-working-memory-is-persisted-only-when-valid.md +0 -25
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +0 -39
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +0 -23
- package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +0 -27
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +0 -25
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +0 -22
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +0 -20
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +0 -22
- package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +0 -26
- package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +0 -66
- package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +0 -22
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +0 -30
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +0 -31
- package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +0 -33
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +0 -29
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +0 -28
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +0 -27
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +0 -28
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +0 -34
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +0 -29
- package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +0 -84
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +0 -41
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +0 -44
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +0 -39
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +0 -42
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +0 -39
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +0 -43
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +0 -38
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +0 -44
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +0 -27
- package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +0 -22
- package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +0 -28
- package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +0 -24
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +0 -32
- package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +0 -43
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +0 -28
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +0 -31
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +0 -26
- package/knowledge/decisions/internals/global-middleware-resolves-from-the-root-namespace-too.md +0 -32
- package/knowledge/decisions/internals/hot-reload-reads-the-changed-source-never-a-compiled-copy.md +0 -38
- package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +0 -26
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +0 -32
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +0 -28
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +0 -30
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +0 -26
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +0 -28
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +0 -32
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +0 -26
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +0 -25
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +0 -26
- package/knowledge/decisions/internals/index.md +0 -181
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +0 -25
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +0 -26
- package/knowledge/decisions/internals/mcp-wire-names-are-assigned-over-the-whole-registry.md +0 -39
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +0 -24
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +0 -53
- package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +0 -21
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +0 -28
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +0 -27
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +0 -31
- package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +0 -30
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +0 -32
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +0 -31
- package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +0 -24
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +0 -26
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +0 -27
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +0 -48
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +0 -30
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +0 -28
- package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +0 -34
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +0 -24
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +0 -26
- package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +0 -43
- package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +0 -22
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +0 -30
- package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +0 -83
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +0 -29
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +0 -27
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +0 -40
- package/knowledge/decisions/internals/the-mcp-handshake-is-challenged-only-when-every-target-is-gated.md +0 -29
- package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +0 -40
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +0 -40
- package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +0 -24
- package/knowledge/decisions/internals/the-runner-resolves-wire-services-itself.md +0 -31
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +0 -26
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +0 -25
- package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +0 -21
- package/knowledge/decisions/internals/the-virtual-user-prompt-says-json-because-of-json-object-mode.md +0 -22
- package/knowledge/decisions/internals/the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md +0 -28
- package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +0 -22
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +0 -25
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +0 -33
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +0 -26
- package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +0 -43
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +0 -115
- package/knowledge/decisions/internals/virtual-user-conversation-drives-the-target-through-a-transport-seam.md +0 -24
- package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +0 -25
- package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +0 -23
- package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +0 -21
- package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +0 -30
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +0 -24
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +0 -26
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +0 -25
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +0 -58
- package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +0 -35
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +0 -34
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +0 -42
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +0 -38
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +0 -29
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +0 -42
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +0 -25
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +0 -29
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +0 -43
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +0 -29
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +0 -42
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +0 -33
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +0 -32
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +0 -31
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +0 -39
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +0 -29
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +0 -33
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +0 -37
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +0 -54
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +0 -43
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +0 -32
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +0 -18
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +0 -34
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +0 -29
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +0 -33
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +0 -34
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +0 -34
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +0 -38
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +0 -30
- package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +0 -26
- package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +0 -20
- package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +0 -23
- package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +0 -16
- package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +0 -26
- package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +0 -32
- package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +0 -27
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +0 -28
- package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +0 -33
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +0 -37
- package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +0 -33
- package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +0 -33
- package/knowledge/decisions/security/a-public-function-says-so-with-auth-false.md +0 -34
- package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +0 -25
- package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +0 -52
- package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +0 -27
- package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +0 -26
- package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +0 -25
- package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +0 -29
- package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +0 -25
- package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +0 -37
- package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +0 -24
- package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +0 -29
- package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +0 -30
- package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +0 -38
- package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +0 -23
- package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +0 -27
- package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +0 -41
- package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +0 -25
- package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +0 -32
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +0 -50
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +0 -43
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +0 -52
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +0 -46
- package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +0 -20
- package/knowledge/decisions/security/agent-approval-forwarding-requires-a-symbol-brand.md +0 -27
- package/knowledge/decisions/security/agent-credential-requests-are-symbol-branded.md +0 -37
- package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +0 -31
- package/knowledge/decisions/security/agent-ownership-failures-never-echo-the-resource.md +0 -23
- package/knowledge/decisions/security/agent-resume-re-runs-the-authorization-gate.md +0 -22
- package/knowledge/decisions/security/agent-sessionless-deployments-have-no-thread-ownership.md +0 -39
- package/knowledge/decisions/security/agent-thread-ownership-composes-the-session-principal.md +0 -30
- package/knowledge/decisions/security/agent-tool-filtering-reads-the-live-function-config.md +0 -24
- package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +0 -26
- package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +0 -33
- package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +0 -16
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +0 -33
- package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +0 -26
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +0 -59
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +0 -30
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +0 -52
- package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +0 -38
- package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +0 -31
- package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +0 -18
- package/knowledge/decisions/security/an-mcp-refusal-is-decided-before-dispatch.md +0 -48
- package/knowledge/decisions/security/an-oauth2-credential-is-read-by-its-account-row.md +0 -40
- package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +0 -32
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +0 -24
- package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +0 -24
- package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +0 -26
- package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +0 -27
- package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +0 -25
- package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +0 -18
- package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +0 -29
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +0 -84
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +0 -39
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +0 -37
- package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +0 -22
- package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +0 -29
- package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +0 -27
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +0 -41
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +0 -30
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +0 -40
- package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +0 -25
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +0 -33
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +0 -46
- package/knowledge/decisions/security/index.md +0 -135
- package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +0 -21
- package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +0 -38
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +0 -27
- package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +0 -18
- package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +0 -22
- package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +0 -26
- package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +0 -24
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +0 -40
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +0 -31
- package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +0 -35
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +0 -69
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +0 -39
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +0 -34
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +0 -55
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +0 -30
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +0 -28
- package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +0 -31
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +0 -34
- package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +0 -22
- package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +0 -34
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +0 -37
- package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +0 -26
- package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +0 -24
- package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +0 -16
- package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +0 -21
- package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +0 -24
- package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +0 -34
- package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +0 -16
- package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +0 -29
- package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +0 -23
- package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +0 -25
- package/knowledge/decisions/security/virtual-user-conversation-missing-approval-decisions-default-to-denied.md +0 -22
- package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +0 -18
- package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +0 -25
- package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +0 -42
- package/knowledge/decisions/security/virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +0 -29
- package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +0 -29
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +0 -25
- package/knowledge/decisions/security/wire-addon-expose-selects-the-rpc-surface.md +0 -51
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +0 -40
- package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +0 -18
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md +0 -32
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +0 -31
- package/knowledge/decisions/security/workflow-virtual-user-steps-always-use-the-real-transport.md +0 -34
- package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +0 -18
- package/knowledge/index.md +0 -24
- package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +0 -24
- package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +0 -35
- package/knowledge/questions/dev-quick-login-as-impersonation.md +0 -25
- package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +0 -26
- package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +0 -27
- package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +0 -26
- package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +0 -26
- package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +0 -34
- package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +0 -20
- package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +0 -24
- package/knowledge/questions/does-the-store-session-match-the-other-two.md +0 -19
- package/knowledge/questions/index.md +0 -41
- package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +0 -21
- package/knowledge/questions/live-scheduled-tests-may-write.md +0 -19
- package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +0 -23
- package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +0 -32
- package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +0 -25
- package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +0 -23
- package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +0 -35
- package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +0 -23
- package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +0 -27
- package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +0 -26
- package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +0 -20
- package/knowledge/questions/staging-impersonation-rules.md +0 -27
- package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +0 -44
- package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +0 -34
- package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +0 -20
- package/knowledge/questions/what-an-impersonated-session-carries.md +0 -22
- package/run-tests.sh +0 -68
- package/scripts/generate-api-report.d.mts +0 -1
- package/scripts/generate-api-report.mjs +0 -96
- package/scripts/generate-api-report.mts +0 -333
- package/src/public-surface.json +0 -637
- package/src/public-surface.json.README +0 -43
- /package/dist/{function/compensation-name.d.ts → compensation-name.d.ts} +0 -0
- /package/dist/{function/compensation-name.js → compensation-name.js} +0 -0
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: overview
|
|
3
|
-
title: Internals
|
|
4
|
-
description: How core behaves — runtime constraints, execution semantics, and the shapes the API commits to
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Internals
|
|
8
|
-
|
|
9
|
-
A rule about how core behaves: what runs where, in what order, and what a
|
|
10
|
-
caller is entitled to assume.
|
|
11
|
-
|
|
12
|
-
<!-- pikku:knowledge-index -->
|
|
13
|
-
- [A credential name declared twice must agree on its schema and its type](a-credential-name-declared-twice-must-agree-on-schema-and-type.md) — validateAndBuildCredentialDefinitionsMeta throws when two declarations of one credential name differ in schema or in type, and otherwise keeps the first declaration
|
|
14
|
-
- [declareScopes lets an app grant a scope whose addon it does not wire](a-grant-can-name-a-scope-declared-without-its-addon.md) — defineScope is a no-op read by the CLI, and declareScopes declares scope ids so a grant is valid without wiring the addon that owns the scope tree
|
|
15
|
-
- [A held run is woken later, not retried](a-held-run-is-woken-later-not-retried.md) — An orchestrator message that finds its run held enqueues a fresh wake-up a second later instead of failing, because the queue's retry budget is for real failures and a long pass outlasts it
|
|
16
|
-
- [A non-streaming agent run registers with agentRunState on the same terms as a streaming one](a-non-streaming-agent-run-registers-with-agentrunstate-too.md) — Otherwise interruptAgent finds the run, passes the ownership check, then cannot stop it — and reports that as if the run were on another host
|
|
17
|
-
- [With scenarios.reset on, the dev seed is the fixture every assertion is written against](a-reset-suite-makes-the-dev-seed-the-fixture.md) — The rollback restores the database as the suite found it, so seed rows are the shared baseline — which makes an absolute date in the seed a test that expires
|
|
18
|
-
- [A resumed turn is as interruptible as the first one](a-resumed-agent-turn-is-as-interruptible-as-the-first.md) — It is the same person listening to the same voice, and after an approval it is where most of the reply actually gets spoken
|
|
19
|
-
- [A scenario step's prose template is offered to a virtual user unfilled](a-scenario-step-template-is-offered-unfilled.md) — A reporter fills placeholders from a run that happened; there is no run yet, and the filled form would answer the question the user is there to answer
|
|
20
|
-
- [A scheduled task writes its caller's session to the session store before it runs](a-scheduled-task-writes-its-caller-session-before-it-runs.md) — runScheduledTask stores the session it is passed, or nothing, before it looks up the task, so the run uses only a session its caller supplied
|
|
21
|
-
- [A secret set in memory shadows the variable of the same name](a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md) — LocalSecretService reads its in-memory map before the variables service, stores a SecretValue unwrapped, and treats an empty string as absent
|
|
22
|
-
- [A secret that fails to decrypt fails the whole read](a-secret-that-fails-to-decrypt-fails-the-whole-read.md) — getSecrets throws naming the key and its key_version rather than omitting the row, because a silent omission surfaces as an unrelated failure much later
|
|
23
|
-
- [A virtual user acts through invokeRaw, so a refusal is data it can act on](a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md) — virtualUserTarget calls virtualUser.invokeRaw, which signs the virtual user in when needed, retries once after a 401, and returns the status instead of throwing
|
|
24
|
-
- [A virtual user cadence is a row, not a timer](a-virtual-user-cadence-is-a-row-not-a-timer.md) — How often a virtual user runs is stored as a due time per virtual user and acted on by a tick the project schedules — pikku never starts a timer, and a run never reschedules itself
|
|
25
|
-
- [A virtual user's converse signs in before its first turn](a-virtual-user-converse-signs-in-before-its-first-turn.md) — HttpVirtualUser.converse calls login() before a run when it holds no session, because a public agent route never triggers the 401 retry that would sign the virtual user in
|
|
26
|
-
- [A virtual user decides whether to trust its notes once per turn, by one roll](a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md) — The difference between the stale, newcomer and auditor dispositions is expressed as a single probability rather than as prose in each prompt
|
|
27
|
-
- [A virtual user's email is computed from its id, with the run id as a sub-address](a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md) — virtualUserEmail derives the address from the virtual user id and a real domain, appends the run id so concurrent runs get separate inboxes and accounts, and refuses colliding addresses
|
|
28
|
-
- [A virtual user run is not a workflow, but it needs a trigger](a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md) — runVirtualUser writes its record and dispatches the run onto a queue at one attempt — an exploratory run has nothing to replay, but a deployment that puts each function in its own unit has nothing to fire it either
|
|
29
|
-
- [A wall-clock threshold is a load test in disguise](a-wall-clock-threshold-is-a-load-test-in-disguise.md) — The KEK derivation test asserted a fixed 50ms budget for work that took 10ms, which went red about one run in five once the suite was large enough to compete for the machine
|
|
30
|
-
- [A workflow's wire is built from the run record, not from the RPC service](a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md) — The RPC service exposes no wire, so every rpcService.wire read was undefined; the run record is the only thing that carries the caller across a step boundary
|
|
31
|
-
- [Addon package roots resolve by walking node module search paths](addon-package-roots-resolve-by-walking-node-module-search-paths.md) — LocalMetaService finds an addon's directory by scanning resolve.paths, not by require.resolve, because addon packages expose no main entry
|
|
32
|
-
- [An addon's .pikku meta ships at the package root or under dist, and readers probe both](addon-pikku-meta-ships-at-the-package-root-or-under-dist.md) — The layout depends on the addon's build and files field, so a consumer resolving the directory by path must try `<pkg>/.pikku` and `<pkg>/dist/.pikku` before concluding an addon declares nothing
|
|
33
|
-
- [Addon singleton services are cached per namespace, not per package](addon-singleton-services-are-cached-per-namespace-not-per-package.md) — Each wireAddon instance gets its own services built from its own overrides, at the cost of one service graph per wired instance
|
|
34
|
-
- [Bare workflow names from inside an addon are prefixed with the consumer's namespace](addon-workflow-names-are-prefixed-with-the-consumer-namespace.md) — The addon's workflowService is proxied so an addon never has to hardcode the name its consumer chose
|
|
35
|
-
- [The AG-UI bridge obeys the client's event-ordering contract exactly](agent-agui-bridge-obeys-the-client-ordering-contract.md) — RUN_STARTED opens lazily, RUN_FINISHED fires once on done, and step names are globally sequential — a violation makes the client drop the whole stream
|
|
36
|
-
- [Audio chunks are labelled with the format the provider actually returned](agent-audio-chunks-carry-the-format-the-provider-returned.md) — The configured format is only a request, so the response's own format wins with the request and pcm16 as fallbacks
|
|
37
|
-
- [Loading agent context waits for a tool result that may still be landing](agent-context-waits-for-a-tool-result-still-being-written.md) — An interrupted run's tool can still be writing to the thread, and in voice the next turn arrives within seconds — soon enough to load context missing what it is about to be asked about
|
|
38
|
-
- [A credential-required tool result never reaches the client or the transcript](agent-credential-suspensions-hide-the-tool-result.md) — The run suspends with credential-request events instead, leaving the tool call unresulted so it can be resumed after connecting
|
|
39
|
-
- [Delegate mode hides the parent's later text, supervise mode hides the sub-agent's](agent-delegate-and-supervise-hide-different-text.md) — Exactly one voice reaches the client per agent-mode; approvals and tool events always flow through either way
|
|
40
|
-
- [Nulls are stripped from approved tool arguments before execution](agent-llm-tool-arguments-have-nulls-stripped.md) — LLMs emit null for optional fields where the schema layer expects undefined, so a resumed tool call is cleaned recursively first
|
|
41
|
-
- [Model resolution stays a single seam even though it is currently a passthrough](agent-model-config-stays-a-single-resolution-seam.md) — resolveModelConfig looks removable but is the one merge point for per-request model overrides
|
|
42
|
-
- [An agentMiddleware onError hook cannot change how a run fails](agent-onerror-hooks-cannot-change-the-failure.md) — Hook throws are swallowed so observability code can never convert, mask, or replace the original error
|
|
43
|
-
- [AI runner methods must be called on the runner, never as detached references](agent-runner-methods-must-keep-their-receiver.md) — Implementations use this internally, so grabbing transcribe or generateSpeech as a bare function loses the receiver and throws at runtime
|
|
44
|
-
- [Agent speech travels as a CUSTOM AG-UI event rather than being dropped](agent-speech-travels-as-a-custom-agui-event.md) — AG-UI has no speech event, and dropping it makes a voice agent reached over HTTP silently inaudible while the provider still bills for the audio
|
|
45
|
-
- [Persisting an agent stream from send is best-effort and must never reject](agent-stream-persistence-is-best-effort.md) — The persisting channel flushes fire-and-forget because send is synchronous; a storage failure degrades the transcript instead of killing the process
|
|
46
|
-
- [A delegated sub-agent inherits the parent run's context block](agent-sub-agents-inherit-the-parent-context-block.md) — The sub-agent tool schema carries only message and session, so the parent's identifier block is forwarded rather than re-typed by the model
|
|
47
|
-
- [A tool's execute() failure is logged before the AI SDK swallows it](agent-tool-execute-failures-are-logged-unconditionally.md) — Every agent tool is wrapped in a logging try/catch, because a thrown tool error otherwise becomes a conversational reply and is invisible server-side
|
|
48
|
-
- [Voice input transcribes audio parts sequentially and in place](agent-voice-input-transcribes-audio-parts-in-place.md) — Each audio part is replaced by its text where it sat, one at a time, bounding concurrent downloads and preserving content order
|
|
49
|
-
- [Working memory is persisted only when the merged value validates](agent-working-memory-is-persisted-only-when-valid.md) — A failed schema check logs and drops the update rather than saving it, because invalid state poisons every later read
|
|
50
|
-
- [An addon's scope root loses to a root the host app already declares](an-addon-scope-root-loses-to-a-root-the-host-already-declares.md) — loadAddonFunctionsMeta merges addon scope trees by root name, first declaration wins, so an addon sharing a root with its host contributes nothing — silently
|
|
51
|
-
- [An interrupt is not a failure, and the non-streaming path throws rather than returning](an-agent-interrupt-is-not-a-failure.md) — It skips the onError hooks and never becomes an errorMessage; with no partial reply to hand back, a typed throw is what distinguishes it from a provider outage
|
|
52
|
-
- [A reachable agent is offered by its registry key, filtered by the virtual user's scopes](an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md) — reachableAgents offers an agent to a virtual user under the key it is registered with, and only when the virtual user holds the agent's declared scopes; the server still enforces access
|
|
53
|
-
- [An interrupt for a run owned by another instance says so, rather than returning false](an-agent-run-owned-by-another-instance-says-so.md) — A bare false is indistinguishable from "already finished", which is the one deployment shape the in-process registry cannot cover
|
|
54
|
-
- [A wrapped agent-stream send must return the inner send's promise](an-agent-stream-send-must-return-the-inner-sends-promise.md) — Middleware runs asynchronously, so dropping the returned promise turns every awaited channel.send upstream into a no-op
|
|
55
|
-
- [A message with nothing to say carries no text part at all](an-empty-text-part-is-omitted-from-an-agent-message.md) — An attachment on its own is a real turn, and providers are entitled to reject an empty text part sitting beside it
|
|
56
|
-
- [A transcript is recorded only when something was actually heard](an-empty-transcript-is-not-recorded.md) — Recording an empty string sends a transcript event saying the user said nothing, which renders as an empty bubble rather than a pending one
|
|
57
|
-
- [An OAuth2 credential implies its app client secret, optional and overridable by declaration](an-oauth2-credential-implies-an-optional-app-secret.md) — deriveOAuth2AppSecrets creates the app client id and secret for each OAuth2 credential, marked optional, unless the project already declares that secret id
|
|
58
|
-
- [An unref'd timer cannot be awaited under node:test](an-unref-d-timer-cannot-be-awaited-under-node-test.md) — The channel RPC registry unrefs its timeout so a pending call never holds a process open, which makes that timeout unawaitable in a test and silently cancels the rest of the file
|
|
59
|
-
- [Analytics identity resolvers run in declared order so consent is read before a cookie is minted](analytics-identity-resolvers-run-in-declared-order.md) — composeAnalyticsIdentity threads each resolver's output into the next, so a cookie-minting resolver sees the consent that an earlier resolver read
|
|
60
|
-
- [Channel message handlers accept three config shapes](channel-message-handlers-accept-three-config-shapes.md) — onMessage may be a function config, a wrapper with middleware, or a wrapper around a function config — the runtime discriminates structurally
|
|
61
|
-
- [Channel middleware caching covers only statically resolved middleware](channel-middleware-caches-only-statically-resolved-middleware.md) — Inherited tag/named middleware is cached per uid; per-run closures are appended fresh every call, at the cost of re-allocating the array
|
|
62
|
-
- [`getState<T>()` lets the caller name any type, so every implementation asserts](channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md) — The type parameter appears only in the return position with nothing to infer from, so it is a caller-chosen claim rather than a checked fact
|
|
63
|
-
- [Channel state is per-socket, session state is per-user](channel-state-is-per-socket-session-state-is-per-user.md) — ChannelStore holds connection-scoped scratch data keyed by channelId, deliberately separate from the pikkuUserId-keyed SessionStore
|
|
64
|
-
- [A channel's user id is persisted only after onConnect middleware has run](channel-user-id-is-persisted-after-onconnect-middleware-runs.md) — The channelId to pikkuUserId mapping is written post-onConnect, because auth middleware is what establishes the session
|
|
65
|
-
- [CLI option names are camelCase in state and kebab-case on the command line](cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md) — Option keys match the function's input field names so they can be plucked by schema, and are converted to kebab only for display and parsing
|
|
66
|
-
- [CLI parse errors are routed by message prefix](cli-parse-errors-are-routed-by-message-prefix.md) — The CLI runners decide between printing help and printing errors by string-matching the prefixes the parser writes, so those message strings are an interface
|
|
67
|
-
- [CLI stdout is reserved for machine-readable output](cli-stdout-is-reserved-for-machine-readable-output.md) — The default renderer emits single-line NDJSON, diagnostics go to stderr, and --json only hijacks rendering for commands that declared a renderer
|
|
68
|
-
- [CLI unknown long options warn instead of failing](cli-unknown-long-options-warn-instead-of-failing.md) — Unrecognised --long options are accepted, warned about and dropped so older binaries tolerate newer invocations, while unknown short flags stay hard errors
|
|
69
|
-
- [A column's at-rest form is an axis of its own](core-column-form-is-an-axis-of-its-own.md) — How a value is stored is independent of how sensitive it is, so form carries a required nominal brand on writes while classification stays optional on reads
|
|
70
|
-
- [The data-classification brand is an optional property](core-data-classification-brand-is-an-optional-property.md) — Making __classification__ required would break ordinary Kysely operands, so the brand only constrains values flowing out
|
|
71
|
-
- [The function runner restores the wire fields it overwrites](core-function-runner-restores-the-wire-fields-it-overwrites.md) — One wire object is reused across nested calls, so functionId, audit, addonNamespace and rpc are saved and put back in a finally
|
|
72
|
-
- [Hot reload merges generated meta and never replaces it](core-hot-reload-merges-generated-meta-never-replaces-it.md) — Reloading codegen output must preserve runtime-registered meta, which no generated JSON contains
|
|
73
|
-
- [Hot reload owns its module registry instead of re-importing](core-hot-reload-owns-its-module-registry.md) — Dev reload transpiles to CJS and runs modules through vm.compileFunction, because the native ESM loader map cannot be evicted
|
|
74
|
-
- [Middleware order is resolution scope first, then priority](core-middleware-order-is-scope-then-priority.md) — Middleware is collected global to function, then stably sorted by priority, deduped, frozen and cached per wire
|
|
75
|
-
- [Schema defaults are applied on every transport, not just HTTP](core-schema-defaults-apply-on-every-transport.md) — Defaults belong to the schema rather than the call's encoding, so they run unconditionally and are cloned per request
|
|
76
|
-
- [Scopes are an AND gate, separate from permissions](core-scopes-are-an-and-gate-separate-from-permissions.md) — Every declared scope must be held, so adding one can only narrow access — permissions OR, and can only widen it
|
|
77
|
-
- [Pikku state is a global map written only at registration time](core-state-is-a-global-map-written-only-at-registration-time.md) — A symbol-keyed globalThis map holds the wiring registry; nothing per-request may ever be written to it
|
|
78
|
-
- [Email meta is read uncached because codegen rewrites it mid-session](email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md) — getEmailMeta re-reads its file on every call, unlike every other meta accessor, because the file appears and changes during a long-lived session
|
|
79
|
-
- [Feature flag declarations refuse an empty anyOf and conflicting scopes](feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md) — validateAndBuildFeatureFlagDefinitionsMeta throws on an anyOf that is an empty list, and on a repeated flag name whose scopes differ between declarations
|
|
80
|
-
- [Feature flags fail open on availability and never enforce access](feature-flags-fail-open-and-never-enforce-access.md) — A flag with no config row is available by default, anyOf decides only the advisory capable half, and the runner's assertFeatureAvailable checks availability alone
|
|
81
|
-
- [Flag declaration sync rewrites only the description and anyOf](flag-sync-rewrites-only-the-declared-text.md) — The FeatureFlagStore contract re-syncs a flag's description and anyOf on deploy and leaves enabled, rollout and overrides to the operator
|
|
82
|
-
- [Gateway adapters resolve lazily and are promise-cached](gateway-adapters-resolve-lazily-and-are-promise-cached.md) — wireGateway accepts an adapter factory because real adapters need boot-time secrets, which forces the webhook GET route to be registered unconditionally
|
|
83
|
-
- [Gateway middleware sees wire.rpc on webhook and websocket, but not on listener](gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md) — The listener transport invokes its handler directly, so middleware runs outside any runPikkuFunc call and the lazily-attached rpc is absent
|
|
84
|
-
- [Gateway webhook challenges echo bytes not JSON](gateway-webhook-challenges-echo-bytes-not-json.md) — String verification challenges are returned raw with returnsJSON false, because platforms byte-compare the echo and JSON quoting fails the handshake
|
|
85
|
-
- [Gateway wiring is a meta-wiring over HTTP and channels](gateway-wiring-is-a-meta-wiring-over-http-and-channels.md) — wireGateway writes handler implementations into the HTTP and channel state directly while the inspector compiles the corresponding meta, so runtime registration deliberately writes no meta
|
|
86
|
-
- [Generated src paths in pikku meta are absolute](generated-src-paths-in-pikku-meta-are-absolute.md) — emailsMeta.src is resolved by the CLI at generation time, so reading through the project-relative helpers produces a wrong compound path
|
|
87
|
-
- [Global middleware resolves from the root namespace too](global-middleware-resolves-from-the-root-namespace-too.md) — An addon's dispatch carries the addon's package name, so reading globals from that namespace alone meant the application's own global middleware never ran for it
|
|
88
|
-
- [Hot reload reads the changed source, never a compiled copy of it](hot-reload-reads-the-changed-source-never-a-compiled-copy.md) — A leftover .js beside a .ts made the reloader announce a reload while re-registering the previous implementation; project TypeScript is now compiled by the reloader itself
|
|
89
|
-
- [Hot reload writes into the function map captured at startup, not pikkuState's current one](hot-reload-writes-into-the-function-map-captured-at-startup.md) — A dev-server watcher may have swapped in a codegen-scoped map whose writes are discarded on restore, and schemas are deliberately left alone
|
|
90
|
-
- [HTTP request bodies are read once and shared between consumers](http-request-bodies-are-read-once-and-shared.md) — The fetch request wrapper memoises the single-use body and builds web Requests lazily, at the cost of holding the whole body in memory
|
|
91
|
-
- [HTTP route groups cascade config in a fixed, per-field order](http-route-groups-cascade-config-in-a-fixed-order.md) — basePath concatenates, tags and middleware merge outward-in, auth is overridden by the innermost group
|
|
92
|
-
- [The HTTP router matches normalized paths but returns the registered path](http-router-matches-normalized-paths-but-returns-registered-ones.md) — Matching normalizes the leading slash while the match result carries the original key, because pikkuState is keyed by the registered string
|
|
93
|
-
- [The HTTP runner logs through a trace-scoped logger, functions do not](http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md) — Only runner-internal logging is scoped to the request id; functions keep the singleton logger for compatibility
|
|
94
|
-
- [Set-Cookie headers are appended individually, never joined](http-set-cookie-headers-are-appended-never-joined.md) — Every cookie gets its own header line, because Set-Cookie is the one header comma-joining corrupts
|
|
95
|
-
- [HTTP SSE streams flush headers only after middleware has run](http-sse-streams-flush-headers-only-after-middleware.md) — SSE responses defer the header flush and register with the eventHub, at the cost of a stricter ordering the runner must preserve
|
|
96
|
-
- [HTTP wiring without generated metadata is skipped, not fatal](http-wiring-without-metadata-is-skipped-not-fatal.md) — wireHTTP warns and returns when a route has no metadata, so partial deploy units still boot
|
|
97
|
-
- [In a scenario a 4xx is data, not an exception](in-a-scenario-a-4xx-is-data-not-an-exception.md) — postScenarioJson and invokeRaw report the status instead of throwing, because a refusal is the expected outcome of a permissions scenario
|
|
98
|
-
- [In-memory workflow history aliases the live step object](in-memory-workflow-history-aliases-the-live-step-object.md) — stepHistory pushes the same StepState reference that steps holds, so later mutations to a step are visible in its history entry
|
|
99
|
-
- [Istanbul statement counts attach to the start line only](istanbul-statement-counts-attach-to-the-start-line-only.md) — The istanbul coverage reader credits a statement's hits to its first line, so an enclosing multi-line statement cannot mask an unexecuted inner one
|
|
100
|
-
- [Local trigger and gateway services assume a single process](local-trigger-and-gateway-services-assume-a-single-process.md) — InMemoryTriggerService and LocalGatewayService start every listener unconditionally with no distributed claiming, so a second instance duplicates every event
|
|
101
|
-
- [MCP wire names are assigned over the whole registry, not derived per name](mcp-wire-names-are-assigned-over-the-whole-registry.md) — Sanitising each name on its own is lossy — `a:b` and `a.b` both become `a_b` — so one of the two targets would be unreachable
|
|
102
|
-
- [Node-only builtins are imported dynamically](node-only-builtins-are-imported-dynamically.md) — V8CoverageService imports node:inspector inside start() so the module stays loadable on runtimes that have no such builtin
|
|
103
|
-
- [One project-shape check, called by both validators](one-project-shape-check-two-validators.md) — workspace validate and cloud validate were separate walks over the same project that duplicated sixteen findings verbatim; the shared half now lives in shared-checks.ts and cloud validate is that plus the deploy-shaped checks
|
|
104
|
-
- [Only functions marked `expose: true` enter a virtual user's catalogue](only-exposed-functions-enter-a-virtual-user-catalogue.md) — Absent is not permissive — an unexposed function 404s over rpc, so offering one spends a step to learn nothing about the product
|
|
105
|
-
- [Queue group concurrency keeps one shared queue fair](queue-group-concurrency-keeps-one-shared-queue-fair.md) — Per-group slot caps let many producers share a single queue instead of one queue each, at the cost of a cap that must stay under batchSize
|
|
106
|
-
- [Queue jobs always carry an explicit attempts count](queue-jobs-always-carry-an-explicit-attempts-count.md) — resolveJobOptions always passes attempts so a queue backend can never apply its own retry default, and an explicit retries of 0 is honoured
|
|
107
|
-
- [Remote addons dispatch over HTTP instead of through local function meta](remote-addons-dispatch-over-http-instead-of-local-meta.md) — wireRemoteAddon ships the addon as a devDependency and posts to the host, so there is deliberately no local handler to resolve
|
|
108
|
-
- [System role names cannot contain the scope separator, and redeclared roles must grant the same scopes](role-names-cannot-contain-the-scope-separator.md) — validateAndBuildSystemRoleDefinitionsMeta rejects an empty role name or one containing ':', and throws when two declarations of one role name grant different scopes
|
|
109
|
-
- [Bare RPC names resolve through the caller's package scope before root](rpc-names-resolve-through-package-scope-before-root.md) — An addon's own functions win over root RPC meta for bare names, and the resolving scope is returned so it can be threaded into runPikkuFunc
|
|
110
|
-
- [Scenario agent calls retry sign-in only on 401](scenario-agent-calls-sign-in-on-401-only.md) — HttpVirtualUser.sendAgent sends with whatever session the jar holds and signs in only after a 401, so a no-auth agent route never needs a sign-in; converse signs in eagerly instead
|
|
111
|
-
- [`given` and `when` are sugar for each other; `then` is not](scenario-given-and-when-are-sugar-but-then-is-not.md) — The phase decides whether a step's bindings are alternatives or witnesses, so the same step function called as `when` and as `then` runs differently
|
|
112
|
-
- [Scenario meta lives apart from app meta but merges when read off disk](scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md) — Scenarios generate into .pikku/scenarios so no app module imports them, yet MetaService folds them back into the workflow and function meta
|
|
113
|
-
- [Scenario steps return drained response records](scenario-steps-return-drained-response-records.md) — A scenario step hands back ScenarioHttpResponse rather than a Response, because the body stream reads once and the return value crosses into the run record
|
|
114
|
-
- [Scenarios, steps and virtual users live in files named for them, and validate errors when they do not](scenarios-live-in-files-named-for-them.md) — pikkuScenario/pikkuFeature/pikkuScenarioStep must be in *.scenario.ts, *.scenarios.ts or *.steps.ts, and defineVirtualUsers/runVirtualUser in *.virtual-user.ts or *.vu.ts — an error, because the mixing is only cheap to undo while it is one file
|
|
115
|
-
- [Scope roots may be co-declared by an addon and its host app](scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md) — flattenScopeDefinitions dedupes ids because the same root can legitimately be declared twice, and every consumer requires one entry per scope
|
|
116
|
-
- [Serverless channel disconnect must tolerate a missing channel](serverless-channel-disconnect-must-tolerate-a-missing-channel.md) — A failed channel lookup on disconnect returns quietly, because serverless runtimes deliver disconnect more than once
|
|
117
|
-
- [sideEffects is an allowlist, because core genuinely has some](side-effects-are-an-allowlist-not-a-boolean.md) — The error registry is built by addError calls that run on import, so claiming sideEffects:false would let a bundler drop it and leave getErrorResponse unable to find any error
|
|
118
|
-
- [Speech synthesis picks a voice per sentence but announces a limitation once](speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md) — A bilingual reply should speak the half it can, and repeating the notice for every sentence would bury the reply itself
|
|
119
|
-
- [The agent `done` event goes through the middleware and is awaited](the-agent-done-event-goes-through-the-middleware-and-is-awaited.md) — `done` is the only end-of-reply signal a stream hook gets, and buffering hooks flush on it — sending it raw discards work already paid for
|
|
120
|
-
- [The API report pins members, because the export list only pins names](the-api-report-pins-members-not-just-names.md) — public-surface.json catches an export appearing or vanishing; it cannot see a method added to an interface, which is the change that breaks a consumer's build
|
|
121
|
-
- [The core scope validator refuses separator, wildcard and empty scope segments](the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md) — assertSegment rejects a scope segment that contains the colon separator, equals the wildcard, or is empty
|
|
122
|
-
- [The dev queue copies prod timing and serialization semantics](the-dev-queue-copies-prod-timing-and-serialization-semantics.md) — InMemoryQueueService dispatches via setTimeout, retries with backoff, and JSON round-trips every payload so dev behaviour matches a real backend
|
|
123
|
-
- [One door per name — the ecosystem tier and the package root are both gone](the-ecosystem-entry-point-carries-the-adapter-surface.md) — the adapter surface was split onto @pikku/core/ecosystem to keep a stability promise at the root; publishing every module twice cost more than the promise was worth, so both the facades and the root barrel were deleted
|
|
124
|
-
- [The embedding model is pinned per service and doc/query embedding is split](the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md) — AIEmbeddingService fixes its model at construction so index and query share a vector space, and separates embedDocuments from embedQuery for asymmetric models
|
|
125
|
-
- [The in-memory workflow service is inline-only and single-process](the-in-memory-workflow-service-is-inline-only-and-single-process.md) — InMemoryWorkflowService wires no queues and implements withRunLease/withStepLock as pass-throughs, because inline execution has no second holder to exclude
|
|
126
|
-
- [The KEK salt is scoped to the key version, not the secret](the-kek-salt-is-scoped-to-the-key-version.md) — One stored salt per key version means N secrets cost one derivation, which is the point of envelope encryption
|
|
127
|
-
- [The MCP handshake is challenged only when every target is gated](the-mcp-handshake-is-challenged-only-when-every-target-is-gated.md) — A client decides whether a server speaks OAuth from the handshake alone, so a fully-gated server that answers initialize with a 200 is detected as needing no sign-in
|
|
128
|
-
- [The middleware resolution cache is deliberately unbounded](the-middleware-resolution-cache-is-deliberately-unbounded.md) — Its keyspace is the set of registered wires, not request traffic, and middleware is dynamic — so eviction would buy nothing and cost the dedupe guarantee
|
|
129
|
-
- [The per-invocation rpc view is a class, because an object literal with a getter is slow to build](the-per-invocation-rpc-view-is-a-class.md) — An accessor declared on an object literal is defined per instance, which drops the literal off V8's fast construction path — measured at 1.15µs against 0.47µs, on every request
|
|
130
|
-
- [The pikku user id resolves in a fixed order](the-pikku-user-id-resolves-in-a-fixed-order.md) — defaultPikkuUserIdResolver takes an explicit pikkuUserId first, then the session userId, then the queue job's id, then the workflow's id
|
|
131
|
-
- [The function runner resolves wire services itself](the-runner-resolves-wire-services-itself.md) — A function's wire services come from its own package's factory or the app's registered one, never borrowed from whoever called it
|
|
132
|
-
- [The schema service is never stubbed, or tests validate nothing](the-schema-service-is-never-stubbed.md) — createStubProxy returns undefined for the schema property so the real schema service is built — a stubbed one turns validation into a silent no-op
|
|
133
|
-
- [A voice turn's transcript is sent before the run starts, on the raw channel](the-transcript-event-is-sent-ahead-of-the-run.md) — The client does not know what it said, and an answer starts streaming within a few hundred milliseconds — a question arriving after its answer reads as the wrong question
|
|
134
|
-
- [The catalogue is the only gate on what a virtual user may call](the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md) — Narrowing happens once at derivation, so there is no second check in the run loop that could drift out of step with it
|
|
135
|
-
- [The virtual user's instructions say the word "json" because a degraded gateway demands it](the-virtual-user-prompt-says-json-because-of-json-object-mode.md) — A gateway that cannot take a JSON schema falls back to OpenAI's json_object mode, which refuses any request whose prompt does not contain the word
|
|
136
|
-
- [The virtual user runtime is exported from @pikku/core/virtual-user, never from services](the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md) — Those values reach the conversation and agent runners, which no production server runs — and an unbundled deploy loads whatever the import graph names
|
|
137
|
-
- [The worker disposition is the only one not testing anything](the-worker-disposition-is-the-one-that-is-not-testing.md) — It is doing the job, so it abandons rarely, runs cool, and is told to stop and say so rather than guess
|
|
138
|
-
- [Thread history records what the model was asked, which for a spoken turn is the transcript](thread-history-records-the-transcript-not-the-audio.md) — The wire carried a base64 audio blob; persisting it writes megabytes of unreadable data and loses the only readable record of the turn
|
|
139
|
-
- [Trigger declaration is split from trigger source](trigger-declaration-is-split-from-trigger-source.md) — Triggers are declared everywhere but subscribed only in the trigger worker, so app processes never open the underlying subscription
|
|
140
|
-
- [TypedSecretService caches for the process lifetime](typed-secret-service-caches-for-the-process-lifetime.md) — Resolved secrets are cached with no TTL, so a secret rotated out of band is not picked up until restart — tracked as pikkujs/pikku#964
|
|
141
|
-
- [Both validators check virtual users through one shared module, and a virtual user counts from either the meta or the source](validate-checks-virtual-users-through-a-shared-module.md) — workspace validate and cloud validate are separate implementations, so the virtual user/virtual-user/knowledge checks live in virtual-user-checks.ts and are called by both — and a virtual user is counted from the generated meta or a defineVirtualUsers() source scan, whichever answers first
|
|
142
|
-
- [pikku validate runs every applicable check, it does not detect a project kind](validate-runs-checks-by-precondition.md) — one `pikku validate` replaces `pikku workspace validate`; checks declare a precondition and run wherever it holds, because the repos that matter are an app and a pile of addons at the same time
|
|
143
|
-
- [The conversation engine only sees a transport-agnostic target driver](virtual-user-conversation-drives-the-target-through-a-transport-seam.md) — The engine never imports the agent runner; the target is injected as run/approve, so scenarios exercise the real wire path
|
|
144
|
-
- [A conversation verdict is the virtual user's self-evaluation, not an assertion](virtual-user-conversation-verdicts-are-llm-self-evaluations.md) — The engine returns what the virtual user judged plus the transcript; deterministic checks stay with the caller
|
|
145
|
-
- [A virtual user conversation starts from a seeded kickoff message](virtual-user-conversations-seed-a-hidden-kickoff-message.md) — The virtual user's first turn needs a non-empty message list because providers reject an empty prompt; the seed is an instruction and stays out of the transcript
|
|
146
|
-
- [A scenario's step order for a virtual user is insertion order, not a graph traversal](virtual-user-step-order-comes-from-insertion-order.md) — The CLI writes nodes in declaration order, so following `next` would buy an ordering that is already true and cost a traversal that has to interpret branches
|
|
147
|
-
- [Virtual users are declared in exactly one defineVirtualUsers call per codebase](virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md) — defineVirtualUsers is a no-op declaration that the inspector reads statically, and a second call anywhere in the codebase fails the build
|
|
148
|
-
- [Only an explicit `false` silences a spoken reply](voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md) — The key being absent means no voice input is wired and nothing reported either way, so those callers keep the behaviour they had before the option existed
|
|
149
|
-
- [Webhook delivery history records every attempt, best effort](webhook-delivery-history-records-every-attempt-best-effort.md) — The webhook worker persists each attempt before it throws, and a failure to persist is logged rather than allowed to mask the delivery result
|
|
150
|
-
- [Webhook service collaborators are constructor args, not locator lookups](webhook-service-collaborators-are-constructor-args-not-locator-lookups.md) — QueueWebhookService takes its queue as a constructor parameter so a project wiring webhooks without a queue fails to compile instead of at first send
|
|
151
|
-
- [Whether a run is inline is read from the run record](whether-a-run-is-inline-is-read-from-the-run-record.md) — The runContexts map is a read-through cache over WorkflowRun.inline and a lifetime for replay ordinals, never the answer to what a run is
|
|
152
|
-
- [Wiring registries erase the generics their wire* functions capture](wiring-registries-erase-the-generics-their-wire-functions-capture.md) — A registry is typed at unknown so every wiring shares one map; storing a generic config in it needs an assertion, because function parameters are contravariant
|
|
153
|
-
- [Workflow approval expiry is decided from a recorded deadline, not from a timer firing](workflow-approval-expiry-is-decided-from-a-recorded-deadline.md) — The wake-up job is best-effort liveness; losing, duplicating or delaying it cannot change the gate's answer
|
|
154
|
-
- [Core declares the scenario browser surface structurally and never imports a driver](workflow-core-never-imports-a-browser-driver.md) — `@pikku/core` must stay dependency-free for edge runtimes, so playwright augments the interface instead of being imported by it
|
|
155
|
-
- [Workflow DSL meta keeps runtime expressions in their own field, apart from literal values](workflow-dsl-meta-separates-runtime-expressions-from-literals.md) — A string `value` regenerates as a string literal; an `expression` regenerates as code, so the two can never share a field
|
|
156
|
-
- [A feature resolves its scenarios by object identity, never by name or shape](workflow-features-resolve-scenarios-by-object-identity.md) — An unregistered scenario comes back explicitly unresolved rather than silently running as something else
|
|
157
|
-
- [Inline and queued workflow graph runs share one transition planner](workflow-graph-inline-and-queued-runs-share-one-planner.md) — A second, weaker inline traversal would lose joins, cycle revisits and step provenance that the queued path has
|
|
158
|
-
- [Workflow graph node notes are non-semantic and excluded from the graph hash](workflow-graph-node-notes-are-excluded-from-the-graph-hash.md) — Documentation on a node must not count as a topology change, or editing a comment redeploys the workflow
|
|
159
|
-
- [An inline workflow run reports its run id the moment it exists, because a failure throws instead of returning](workflow-inline-runs-report-their-run-id-before-they-can-fail.md) — `onRunCreated` is the only moment guaranteed to happen whether the run passes, fails or suspends
|
|
160
|
-
- [`invocationId` is a workflow step's dedupe key; `stepId` is store-specific and must never be used as one](workflow-invocation-id-is-the-dedupe-key-not-step-id.md) — The invocation id is a frozen UUIDv5 of runId + stepName, identical across retries on every backend
|
|
161
|
-
- [A workflow step goes through the queue only if its function opts in, and there is no inline fallback](workflow-queued-step-dispatch-requires-an-explicit-opt-in.md) — `workflowQueued: true` is the whole decision; a missing queue service is a hard error, not a silent downgrade
|
|
162
|
-
- [Workflows get their own queues by default, and queue names are resolved from queue meta](workflow-queues-are-per-workflow-by-default.md) — Per-workflow queues stop one slow step head-of-line-blocking every other workflow; `shared-groups` trades that for one set of pollers
|
|
163
|
-
- [A workflow step name repeated in one run gets an ordinal suffix, and the first reach stays bare](workflow-repeated-step-names-get-an-ordinal-suffix.md) — `name`, `name#1`, `name#2` keys each reach separately without changing the durable key of any existing run
|
|
164
|
-
- [A workflow replay reads its steps once and caches only the run's immutable half](workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md) — The per-replay snapshot collapses O(N^2) step reads to one, but caching mutable run fields would make the replay read a lie
|
|
165
|
-
- [Workflow step retries are owned by the workflow, never by the queue](workflow-retries-are-owned-by-the-workflow-not-the-queue.md) — A step's retry count is resolved once and always passed to the queue as `attempts`, so the queue can never apply its own default
|
|
166
|
-
- [Workflow run capabilities are extensions, not subclasses](workflow-run-capabilities-are-extensions-not-subclasses.md) — Scenario support lives in a separate module behind `setRunExtension` because a bundler drops an unused module but never an unused class member
|
|
167
|
-
- [The workflow run mirror is an observability sink, never a second source of truth](workflow-run-mirror-is-never-a-source-of-truth.md) — Every mirrored write happens after the authoritative write lands, and a mirror failure can never fail the workflow
|
|
168
|
-
- [Workflow run polling starts short and backs off to the caller's ceiling](workflow-run-polling-backs-off-to-the-callers-ceiling.md) — `pollIntervalMs` is a ceiling, not a cadence, and the wait lives in its own method so the schedule can be asserted without the clock
|
|
169
|
-
- [The workflow run timeline is a pure fold over durable history, with the row's status as the authority](workflow-run-timeline-is-a-pure-fold-over-durable-history.md) — No IO in the fold keeps time-travel transport-independent; the terminal event comes from `status`, not from a timestamp every backend populates
|
|
170
|
-
- [Scenario steps default to no retries, and a whole poll is one durable step](workflow-scenario-assertions-never-retry-and-record-one-step.md) — Retrying a failed assertion is wrong for a test primitive; recording the poll as one step means replay returns the outcome, not the loop
|
|
171
|
-
- [Scenario lifecycle hooks are a scenario-only affordance and never mask the failure they follow](workflow-scenario-hooks-are-a-scenario-only-affordance.md) — A durable workflow replays, so a callback that reruns each replay has no honest meaning there
|
|
172
|
-
- [Scenario prose is rendered out of typed calls, not parsed into them](workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md) — A readable report with no regex step registry to maintain
|
|
173
|
-
- [A quarantined scenario states its reason in code, not in a CI invocation](workflow-scenario-quarantine-reason-lives-in-code.md) — `skip` carries the why next to the scenario it applies to, and naming the scenario explicitly still runs it
|
|
174
|
-
- [Scenario step targets are string literals so the inspector can read them statically](workflow-scenario-step-targets-are-string-literals-for-the-inspector.md) — `step/given/when/then` mirror `do`'s RPC shape because the extractor reads a literal, not an imported symbol
|
|
175
|
-
- [A step's compensation runs as a durable step of its own, declared on the function](workflow-step-compensation-runs-as-its-own-durable-step.md) — A refund or rollback must not fire twice on replay, so it is recorded as `<step>:compensate`; `onError` is gone
|
|
176
|
-
- [A failed workflow step dispatch is transient infrastructure, not a run failure](workflow-step-dispatch-failure-is-transient-not-a-run-failure.md) — Queue-unreachable errors leave the run running and the step pending so the orchestrator replays; marking the run failed loses it
|
|
177
|
-
- [A workflow step lock is held only to claim the step, never across its execution](workflow-step-lock-is-held-only-to-claim-the-step.md) — Holding the step lock across step work exhausted the connection pool and self-deadlocked when it was an advisory lock; it stays claim-only on leases
|
|
178
|
-
- [A workflow step's recorded `rpcName` is provenance only — nothing dispatches off it](workflow-step-rpc-name-is-provenance-only.md) — It exists so a reader can join a runtime step row back to the declaration that produced it, especially when the durable name was built in a loop
|
|
179
|
-
- [A suspend or approval `reason` is the step's durable identity, not just a message](workflow-suspend-and-approval-reasons-are-durable-step-identities.md) — The reason is namespaced and used raw as the step key, so it must be derived deterministically across replays
|
|
180
|
-
- [A suspended workflow run keeps its in-process context; only terminal runs release it](workflow-suspended-runs-keep-their-in-process-context.md) — `suspended` is absent from the terminal set on purpose, and a context is dropped only when nothing is holding it open
|
|
181
|
-
<!-- /pikku:knowledge-index -->
|
package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Istanbul statement counts attach to the start line only
|
|
4
|
-
description: The istanbul coverage reader credits a statement's hits to its first line, so an enclosing multi-line statement cannot mask an unexecuted inner one
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Istanbul statement counts attach to the start line only
|
|
9
|
-
|
|
10
|
-
`IstanbulCoverageService` (`packages/core/src/services/istanbul-coverage-service.ts`)
|
|
11
|
-
reads instrumented counters off the `__coverage__` global and, when turning
|
|
12
|
-
statement maps into line hits, credits each statement's count to its _start_ line
|
|
13
|
-
and no other line it spans.
|
|
14
|
-
|
|
15
|
-
This is istanbul's own semantics, and the reason matters: statements nest. An
|
|
16
|
-
`if` block spanning ten lines has a non-zero count as soon as the `if` is
|
|
17
|
-
reached, and a `throw` on line six inside it that never ran has a count of zero.
|
|
18
|
-
Spreading the enclosing statement's count across its whole range would paint that
|
|
19
|
-
`throw` as covered — the uncovered branch disappears into the covered one, which
|
|
20
|
-
is precisely the case coverage exists to surface.
|
|
21
|
-
|
|
22
|
-
**What this rules out:** filling in `start.line`..`end.line` from a single
|
|
23
|
-
statement's count, or merging a nested statement's zero into its parent's total.
|
|
24
|
-
Any change here has to keep the innermost statement's own count as the authority
|
|
25
|
-
for its line.
|
package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Local trigger and gateway services assume a single process
|
|
4
|
-
description: InMemoryTriggerService and LocalGatewayService start every listener unconditionally with no distributed claiming, so a second instance duplicates every event
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Local trigger and gateway services assume a single process
|
|
9
|
-
|
|
10
|
-
`InMemoryTriggerService` (`packages/core/src/services/in-memory-trigger-service.ts`)
|
|
11
|
-
and `LocalGatewayService` (`packages/core/src/services/local-gateway-service.ts`)
|
|
12
|
-
start every registered trigger source and every listener gateway
|
|
13
|
-
unconditionally. There is no claiming, no lease, no leader election: whoever
|
|
14
|
-
boots, listens.
|
|
15
|
-
|
|
16
|
-
That is correct for exactly one owner. Run two instances and both subscribe to
|
|
17
|
-
the same source, so every external event fires its RPC target twice — and because
|
|
18
|
-
triggers and listener gateways are typically wired to side-effecting functions,
|
|
19
|
-
the duplicate is not idempotent. A distributed deployment needs a different
|
|
20
|
-
`TriggerService` / `GatewayService` implementation that coordinates first; the
|
|
21
|
-
interfaces exist so that implementation can be dropped in.
|
|
22
|
-
|
|
23
|
-
**What this rules out:** scaling a `pikku serve` or container running these
|
|
24
|
-
services beyond one replica, and adding coordination inside these two classes.
|
|
25
|
-
They are the single-process implementations by definition — coordination belongs
|
|
26
|
-
in a sibling implementation, not behind a flag here.
|
package/knowledge/decisions/internals/mcp-wire-names-are-assigned-over-the-whole-registry.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: MCP wire names are assigned over the whole registry, not derived per name
|
|
4
|
-
description: Sanitising each name on its own is lossy — `a:b` and `a.b` both become `a_b` — so one of the two targets would be unreachable
|
|
5
|
-
tags: [mcp, naming]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# MCP wire names are assigned over the whole registry
|
|
9
|
-
|
|
10
|
-
MCP clients constrain tool and prompt names to `[A-Za-z0-9_-]`. Pikku's
|
|
11
|
-
namespace separator is `:`, so every target contributed by an addon — `bb2:getMe`
|
|
12
|
-
and friends — carries a name the client cannot accept. Clients drop such names
|
|
13
|
-
from the session rather than fail the connection, which reads as the tools simply
|
|
14
|
-
not existing. The names are therefore rewritten at the transport boundary and
|
|
15
|
-
resolved back on the way in; the namespace itself is untouched, since it is what
|
|
16
|
-
dispatch keys on.
|
|
17
|
-
|
|
18
|
-
The rewrite is computed for **all** names of a target type at once, not for one
|
|
19
|
-
name in isolation. Replacing illegal characters one name at a time is not
|
|
20
|
-
injective: `a:b` and `a.b` both sanitise to `a_b`, so the list handlers would
|
|
21
|
-
advertise one name twice and the resolver could only ever pick one of them. The
|
|
22
|
-
other target becomes unreachable, silently.
|
|
23
|
-
|
|
24
|
-
The assignment runs in two passes over the sorted names:
|
|
25
|
-
|
|
26
|
-
1. Every name that is already wire-legal claims itself. A target whose name a
|
|
27
|
-
client can already spell keeps that spelling, whatever else is registered.
|
|
28
|
-
2. The rest are sanitised, and a collision takes the next free `_2`, `_3`, …
|
|
29
|
-
suffix.
|
|
30
|
-
|
|
31
|
-
Sorting makes the result depend only on the set of registered names, so the same
|
|
32
|
-
registry always produces the same wire names, across processes and restarts.
|
|
33
|
-
|
|
34
|
-
**What this rules out:** a pure `wireName(name)` function. Correctness here is a
|
|
35
|
-
property of the whole registry, and a signature that cannot see the registry
|
|
36
|
-
cannot have it. It also rules out percent-style escaping, which would be
|
|
37
|
-
injective but would turn every namespaced tool into something unreadable in the
|
|
38
|
-
client's UI, for a collision that needs two targets differing only in their
|
|
39
|
-
separator.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Node-only builtins are imported dynamically
|
|
4
|
-
description: V8CoverageService imports node:inspector inside start() so the module stays loadable on runtimes that have no such builtin
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Node-only builtins are imported dynamically
|
|
9
|
-
|
|
10
|
-
`V8CoverageService` (`packages/core/src/services/v8-coverage-service.ts`) reaches
|
|
11
|
-
`node:inspector` through `await import('node:inspector')` inside `doStart()`,
|
|
12
|
-
not through a top-level import.
|
|
13
|
-
|
|
14
|
-
`@pikku/core` is loaded whole on runtimes that have no Node builtins —
|
|
15
|
-
Cloudflare Workers most notably. A static `import 'node:inspector'` is resolved
|
|
16
|
-
when the module graph loads, so it would fail the entire bundle at startup on
|
|
17
|
-
those runtimes, for a service that would never have been started there anyway.
|
|
18
|
-
Deferring the import moves the failure to the point of use, where it is both
|
|
19
|
-
correct and avoidable.
|
|
20
|
-
|
|
21
|
-
**What this rules out:** hoisting the import to the top of the file because the
|
|
22
|
-
dynamic form "looks unnecessary", and the same move in any other core module that
|
|
23
|
-
touches a Node-only builtin. The rule is general: if core can be loaded on
|
|
24
|
-
Workers, a Node builtin is imported at the call site.
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: One project-shape check, called by both validators
|
|
4
|
-
description: workspace validate and cloud validate were separate walks over the same project that duplicated sixteen findings verbatim; the shared half now lives in shared-checks.ts and cloud validate is that plus the deploy-shaped checks
|
|
5
|
-
tags: cli, validate, cloud
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# One project-shape check, called by both validators
|
|
9
|
-
|
|
10
|
-
`pikku workspace validate` and `pikku validate` read like one command
|
|
11
|
-
with a flag. They were two implementations — 495 lines and 2026 — that walked
|
|
12
|
-
the same project and emitted sixteen identical findings. `functions-dir-missing`
|
|
13
|
-
existed character for character in both files. All sixteen already agreed on
|
|
14
|
-
severity, which is the only reason the duplication was invisible.
|
|
15
|
-
|
|
16
|
-
What the duplication cost was not the lines. It was that each validator carried
|
|
17
|
-
checks the other lacked for no reason anyone could name, and nobody noticed
|
|
18
|
-
because nobody read them side by side:
|
|
19
|
-
|
|
20
|
-
- cloud validate never checked that `packages/functions` declares zod v4, or
|
|
21
|
-
that it has a `package.json` at all — while it did check that six other
|
|
22
|
-
dependencies are present.
|
|
23
|
-
- workspace validate never checked the four scaffold flags beyond `console`,
|
|
24
|
-
though the console it requires is useless without `rpc`.
|
|
25
|
-
- cloud validate swallowed a JSON parse error and reported
|
|
26
|
-
`pikku-config-missing` for a file sitting right there.
|
|
27
|
-
|
|
28
|
-
Two of workspace validate's own checks were not merely absent from cloud — they
|
|
29
|
-
had never run anywhere:
|
|
30
|
-
|
|
31
|
-
- the auth checks were gated on a middleware instance with `definitionId ===
|
|
32
|
-
'betterAuthSession'`, but the CLI wires `betterAuthStatelessSession` whenever
|
|
33
|
-
`session.cookieCache` is on, which is the configuration Pikku Studio Cloud asks for. So
|
|
34
|
-
they skipped precisely the apps most likely to have auth.
|
|
35
|
-
- they looked for migrations in `packages/functions/db/`, and for tables named
|
|
36
|
-
`app_user` and `auth_verification_token`. `pikku db migrate` reads migrations
|
|
37
|
-
from `<root>/db/<engine>/`, and those two table names appear nowhere else in
|
|
38
|
-
pikku or in any template. Had the gate ever opened, the check would have been
|
|
39
|
-
wrong for every project it fired on.
|
|
40
|
-
|
|
41
|
-
`shared-checks.ts` is now the half that is true of any pikku project regardless
|
|
42
|
-
of where it deploys. Workspace validate is exactly that module; cloud validate
|
|
43
|
-
is that module plus the deploy-shaped checks — themes, frontends, the
|
|
44
|
-
Cloudflare adapter, the `.gitignore` contract, the frontend type-check.
|
|
45
|
-
|
|
46
|
-
Pikku Studio Cloud's fix hints won where the two differed: they are multi-line and show the
|
|
47
|
-
config block to paste, and there was no reason workspace users were getting the
|
|
48
|
-
one-line version.
|
|
49
|
-
|
|
50
|
-
**What this rules out:** adding a check to one validator and not the other;
|
|
51
|
-
`pikku validate` reporting a corrupt config as a missing one; asserting
|
|
52
|
-
auth table names no scaffold generates; and reading migrations from anywhere
|
|
53
|
-
other than where `pikku db migrate` reads them.
|
package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Only functions marked `expose: true` enter a virtual user's catalogue
|
|
4
|
-
description: Absent is not permissive — an unexposed function 404s over rpc, so offering one spends a step to learn nothing about the product
|
|
5
|
-
tags: core, virtual-user
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Only functions marked `expose: true` enter a virtual user's catalogue
|
|
9
|
-
|
|
10
|
-
`expose: true` is what puts a function on the rpc transport, which is what the
|
|
11
|
-
shipped target is called over. The catalogue therefore treats an absent `expose`
|
|
12
|
-
as excluded rather than as unspecified-and-allowed.
|
|
13
|
-
|
|
14
|
-
Absent is not permissive here: an unexposed function returns 404, and offering
|
|
15
|
-
it costs the user a step and teaches nothing about the product. On the e2e app,
|
|
16
|
-
34 of 72 functions are in exactly that state — close to half a catalogue that
|
|
17
|
-
cannot be called at all.
|
|
18
|
-
|
|
19
|
-
**What this rules out:** defaulting the check to "include unless explicitly
|
|
20
|
-
hidden", which reads as the safer default and produces a catalogue that is
|
|
21
|
-
mostly dead ends.
|
package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Queue group concurrency keeps one shared queue fair
|
|
4
|
-
description: Per-group slot caps let many producers share a single queue instead of one queue each, at the cost of a cap that must stay under batchSize
|
|
5
|
-
tags: queue
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Queue group concurrency keeps one shared queue fair
|
|
9
|
-
|
|
10
|
-
`PikkuWorkerConfig.groupConcurrency` in
|
|
11
|
-
`packages/core/src/wirings/queue/queue.types.ts` caps how many jobs of any one
|
|
12
|
-
group (`JobOptions.group`, a `JobGroup` with an `id` and optional `tier`) may run
|
|
13
|
-
at once. Jobs sharing a group `id` count against the same limit;
|
|
14
|
-
`GroupConcurrencyConfig.tiers` varies the limit per tier so a slow group can be
|
|
15
|
-
allowed more or fewer slots than the default.
|
|
16
|
-
|
|
17
|
-
The alternative considered was one queue per producer, which gives isolation for
|
|
18
|
-
free. It was rejected because pull-based backends poll per queue, so splitting
|
|
19
|
-
multiplies polling cost linearly with the number of producers. A single shared
|
|
20
|
-
queue plus a per-group cap gets the same "no one producer starves the others"
|
|
21
|
-
property at constant polling cost. The cap must not exceed
|
|
22
|
-
`PikkuWorkerConfig.batchSize`, which is the worker's total concurrency — a group
|
|
23
|
-
limit above it can never bind and silently reverts the queue to unfair.
|
|
24
|
-
|
|
25
|
-
**What this rules out:** dropping `group`/`groupConcurrency` in favour of
|
|
26
|
-
per-producer queues, and raising a group limit to or above `batchSize` as a way
|
|
27
|
-
to "disable" fairness — that reintroduces head-of-line blocking by a single
|
|
28
|
-
producer rather than turning the feature off.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Queue jobs always carry an explicit attempts count
|
|
4
|
-
description: resolveJobOptions always passes attempts so a queue backend can never apply its own retry default, and an explicit retries of 0 is honoured
|
|
5
|
-
tags: services
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Queue jobs always carry an explicit attempts count
|
|
9
|
-
|
|
10
|
-
`QueueWebhookService.resolveJobOptions`
|
|
11
|
-
(`packages/core/src/services/queue-webhook-service.ts`) resolves retries as
|
|
12
|
-
per-call `retries` → `config.webhook.retries` → `DEFAULT_WEBHOOK_RETRIES`, then
|
|
13
|
-
_always_ puts `attempts: retries + 1` on the job options. It mirrors the workflow
|
|
14
|
-
service's policy resolution. Backoff is exponential unless a concrete
|
|
15
|
-
`retryDelay` selects a fixed one.
|
|
16
|
-
|
|
17
|
-
Two rules are load-bearing. `attempts` is passed unconditionally so the queue
|
|
18
|
-
backend never gets to apply its own default — pg-boss, BullMQ and SQS disagree
|
|
19
|
-
about what that default is, and a webhook silently retried a different number of
|
|
20
|
-
times per backend is not a behaviour anyone can reason about. And an explicitly
|
|
21
|
-
set `retries: 0` is honoured rather than treated as unset, because "deliver this
|
|
22
|
-
exactly once, do not retry" is a real caller intent that `??` chains lose.
|
|
23
|
-
|
|
24
|
-
**What this rules out:** omitting `attempts` when it equals the default, folding
|
|
25
|
-
`retries` into a truthiness check (`retries || configRetries`, which turns 0 back
|
|
26
|
-
into the default), and relying on a queue adapter's retry configuration in place
|
|
27
|
-
of passing the value.
|
package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Remote addons dispatch over HTTP instead of through local function meta
|
|
4
|
-
description: wireRemoteAddon ships the addon as a devDependency and posts to the host, so there is deliberately no local handler to resolve
|
|
5
|
-
tags: rpc
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Remote addons dispatch over HTTP instead of through local function meta
|
|
9
|
-
|
|
10
|
-
`wireAddon` bundles an addon's functions in-process: the package is a production
|
|
11
|
-
dependency and its handlers run inside the consumer. `wireRemoteAddon`
|
|
12
|
-
(`packages/core/src/wirings/rpc/wire-remote-addon.ts`) does the opposite — the
|
|
13
|
-
package is installed as a **devDependency**, contributing types only, and the
|
|
14
|
-
handlers run on the host at `serverUrl`. `pikku verify` enforces the
|
|
15
|
-
devDependency placement.
|
|
16
|
-
|
|
17
|
-
`ContextAwareRPCService.invokeAddonFunction` in `rpc-runner.ts` therefore checks
|
|
18
|
-
`resolved.addonConfig?.remote` _before_ it looks for local function meta, and
|
|
19
|
-
routes to `invokeRemoteAddonFunction`. That method POSTs the addon's own function
|
|
20
|
-
name — the bare name, not the namespaced `ns:fn` form, optionally remapped by
|
|
21
|
-
`remoteName` — to `${serverUrl}/remote/rpc/:rpcName`, authenticating as a client
|
|
22
|
-
with the token bound in `wireRemoteAddon({ auth })`. There is no local meta entry
|
|
23
|
-
to fall back on, which is why a missing `serverUrl` raises
|
|
24
|
-
`RemoteAddonConfigError` rather than degrading to a local lookup, and a non-2xx
|
|
25
|
-
response raises `RemoteAddonRequestError` with a truncated body for context.
|
|
26
|
-
|
|
27
|
-
**What this rules out:** moving the `remote` check after the local meta lookup
|
|
28
|
-
(the lookup will always miss and mask the real error), sending the namespaced
|
|
29
|
-
name over the wire, and promoting the addon to a production dependency so its
|
|
30
|
-
handlers can be "used directly" — that defeats the point of the remote wiring and
|
|
31
|
-
puts the host's code in the consumer's bundle.
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: System role names cannot contain the scope separator, and redeclared roles must grant the same scopes
|
|
4
|
-
description: validateAndBuildSystemRoleDefinitionsMeta rejects an empty role name or one containing ':', and throws when two declarations of one role name grant different scopes
|
|
5
|
-
tags: core, roles, scopes, validation
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# System role names cannot contain the scope separator, and redeclared roles must grant the same scopes
|
|
9
|
-
|
|
10
|
-
`packages/core/src/wirings/role/validate-role-definitions.ts` checks declared
|
|
11
|
-
system roles.
|
|
12
|
-
|
|
13
|
-
The separator is `:` (`validate-role-definitions.ts:7`). A name is refused when it
|
|
14
|
-
is empty (`validate-role-definitions.ts:10-12`) or contains the separator
|
|
15
|
-
(`validate-role-definitions.ts:13-18`). The message says the separator "delimits
|
|
16
|
-
scope ids; a role named like a scope reads as one" (`validate-role-definitions.ts:16`).
|
|
17
|
-
|
|
18
|
-
When a name is declared twice, the scope lists are compared after sorting, so order
|
|
19
|
-
does not matter (`validate-role-definitions.ts:69-71`). A different set throws,
|
|
20
|
-
with the message "Roles sharing a name must grant the same scopes"
|
|
21
|
-
(`validate-role-definitions.ts:72-79`). An identical repeat is skipped
|
|
22
|
-
(`validate-role-definitions.ts:80`).
|
|
23
|
-
|
|
24
|
-
`flattenSystemRoleDefinitions` keeps the first entry for each name
|
|
25
|
-
(`validate-role-definitions.ts:36-40`). Its doc comment says this is safe only
|
|
26
|
-
because the validator already guaranteed the repeats are identical
|
|
27
|
-
(`validate-role-definitions.ts:24-29`).
|
|
28
|
-
|
|
29
|
-
**What this rules out:** a role named with a scope-like `:` in it, and two
|
|
30
|
-
declarations of one role that grant different scopes.
|
package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: decision
|
|
3
|
-
title: Bare RPC names resolve through the caller's package scope before root
|
|
4
|
-
description: An addon's own functions win over root RPC meta for bare names, and the resolving scope is returned so it can be threaded into runPikkuFunc
|
|
5
|
-
tags: rpc
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Bare RPC names resolve through the caller's package scope before root
|
|
9
|
-
|
|
10
|
-
`resolvePikkuFunction` in `packages/core/src/wirings/rpc/rpc-runner.ts` tries the
|
|
11
|
-
caller's package function meta first when a `packageName` is supplied, then root
|
|
12
|
-
RPC meta, then a versioned base name, then root function meta, and only then
|
|
13
|
-
throws `RPCNotFoundError`. It returns the resolving package alongside the
|
|
14
|
-
`pikkuFuncId` so `ContextAwareRPCService` can pass the right scope into
|
|
15
|
-
`runPikkuFunc` without a second lookup.
|
|
16
|
-
|
|
17
|
-
The package-first order exists because RPC meta only ever lives in root: addon
|
|
18
|
-
packages register their handlers under their own package name as _function_ meta,
|
|
19
|
-
never as RPC meta. Without the package probe, a bare `rpc('doThing')` made from
|
|
20
|
-
inside an addon would skip that addon's own `doThing` and either resolve to an
|
|
21
|
-
unrelated root function of the same name or fail outright. The versioned retry
|
|
22
|
-
exists so `name@2` falls back to the meta registered under `name`.
|
|
23
|
-
|
|
24
|
-
When even root resolution fails, `rpc` and `rpcWithWire` catch the
|
|
25
|
-
`RPCNotFoundError` and hand the call to `services.deploymentService` if one is
|
|
26
|
-
configured — a Cloudflare service binding or a Lambda invoke — so a name that is
|
|
27
|
-
not in this deploy unit can still be served by another.
|
|
28
|
-
|
|
29
|
-
**What this rules out:** flattening the lookup to a single root meta read,
|
|
30
|
-
resolving the package scope separately from the function id (the two must agree),
|
|
31
|
-
and treating an `RPCNotFoundError` as terminal before the deployment-service
|
|
32
|
-
fallback has had a chance.
|