@pikku/core 0.12.141 → 0.12.142
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/errors/errors.d.ts +1 -1
- package/dist/errors/errors.js +1 -1
- package/dist/function/function-meta.types.d.ts +6 -6
- package/dist/function/functions.types.d.ts +2 -2
- package/dist/services/audit-service.d.ts +4 -4
- package/dist/services/feature-flag-service.d.ts +3 -3
- package/dist/services/{http-personas.d.ts → http-virtual-users.d.ts} +25 -47
- package/dist/services/{http-personas.js → http-virtual-users.js} +29 -53
- package/dist/services/index.d.ts +2 -2
- package/dist/services/index.js +1 -1
- package/dist/services/meta-service.d.ts +6 -6
- package/dist/services/meta-service.js +8 -8
- package/dist/{wirings/workflow → services}/scenario-cookie-jar.d.ts +2 -0
- package/dist/{wirings/workflow → services}/scenario-cookie-jar.js +18 -14
- package/dist/services/system-role-guard.d.ts +1 -1
- package/dist/services/virtual-user-sign-in.d.ts +52 -0
- package/dist/services/virtual-user-sign-in.js +80 -0
- package/dist/services/virtual-user-statement.d.ts +31 -0
- package/dist/services/virtual-user-statement.js +24 -0
- package/dist/services/{personas-service.d.ts → virtual-users-service.d.ts} +25 -23
- package/dist/services/{personas-service.js → virtual-users-service.js} +3 -3
- package/dist/types/core.types.d.ts +11 -11
- package/dist/wirings/role/define-system-role.d.ts +1 -1
- package/dist/wirings/role/define-system-role.js +1 -1
- package/dist/wirings/{actor-flow/actor-flow.types.d.ts → virtual-user/conversation/conversation.types.d.ts} +5 -5
- package/dist/wirings/virtual-user/conversation/index.d.ts +2 -0
- package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +36 -0
- package/dist/wirings/{actor-flow → virtual-user/conversation}/run-conversation.js +30 -30
- package/dist/wirings/virtual-user/define-virtual-users.d.ts +32 -0
- package/dist/wirings/{persona/define-personas.js → virtual-user/define-virtual-users.js} +9 -9
- package/dist/wirings/virtual-user/index.d.ts +30 -7
- package/dist/wirings/virtual-user/index.js +23 -4
- package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +8 -8
- package/dist/wirings/virtual-user/prepare-virtual-user-run.js +9 -9
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +6 -6
- package/dist/wirings/virtual-user/run-virtual-user.js +10 -10
- package/dist/wirings/{persona/validate-personas.d.ts → virtual-user/validate-virtual-users.d.ts} +11 -11
- package/dist/wirings/{persona/validate-personas.js → virtual-user/validate-virtual-users.js} +24 -24
- package/dist/wirings/virtual-user/virtual-user-agents.d.ts +7 -7
- package/dist/wirings/virtual-user/virtual-user-agents.js +2 -2
- package/dist/wirings/{persona/persona-app-scopes.d.ts → virtual-user/virtual-user-app-scopes.d.ts} +10 -10
- package/dist/wirings/{persona/persona-app-scopes.js → virtual-user/virtual-user-app-scopes.js} +12 -12
- package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +3 -3
- package/dist/wirings/virtual-user/virtual-user-catalogue.js +2 -2
- package/dist/wirings/{persona/persona.types.d.ts → virtual-user/virtual-user-declaration.types.d.ts} +24 -24
- package/dist/wirings/virtual-user/virtual-user-derive.js +13 -7
- package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +1 -1
- package/dist/wirings/{persona/persona-email.d.ts → virtual-user/virtual-user-email.d.ts} +11 -11
- package/dist/wirings/{persona/persona-email.js → virtual-user/virtual-user-email.js} +19 -19
- package/dist/wirings/{persona/persona-environments.d.ts → virtual-user/virtual-user-environments.d.ts} +10 -10
- package/dist/wirings/{persona/persona-environments.js → virtual-user/virtual-user-environments.js} +21 -21
- package/dist/wirings/virtual-user/virtual-user-intents.d.ts +3 -3
- package/dist/wirings/virtual-user/virtual-user-intents.js +3 -3
- package/dist/wirings/{persona/persona-mailbox.d.ts → virtual-user/virtual-user-mailbox.d.ts} +4 -4
- package/dist/wirings/virtual-user/virtual-user-run-store.d.ts +4 -4
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +42 -61
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +69 -117
- package/dist/wirings/virtual-user/virtual-user-schedule-store.d.ts +15 -15
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +6 -6
- package/dist/wirings/virtual-user/virtual-user-schedule.js +11 -11
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +6 -6
- package/dist/wirings/virtual-user/virtual-user-target.js +5 -5
- package/dist/wirings/virtual-user/virtual-user.types.d.ts +11 -11
- package/dist/wirings/virtual-user/virtual-user.types.js +1 -1
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +9 -9
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +28 -28
- package/dist/wirings/workflow/pikku-scenario-service.js +77 -77
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.js +4 -4
- package/dist/wirings/workflow/scenario-prose.d.ts +8 -8
- package/dist/wirings/workflow/scenario-prose.js +12 -8
- package/dist/wirings/workflow/scenario-run.types.d.ts +13 -13
- package/dist/wirings/workflow/scenario-step.types.d.ts +23 -23
- package/dist/wirings/workflow/workflow.types.d.ts +2 -2
- package/knowledge/decisions/index.md +0 -2
- package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +29 -0
- package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +29 -0
- package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +22 -0
- package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +28 -0
- package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +32 -0
- package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +12 -12
- package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +24 -0
- package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +34 -0
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +2 -2
- package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +27 -0
- package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +26 -0
- package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +22 -0
- package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +22 -0
- package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +28 -0
- package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +24 -0
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +3 -3
- package/knowledge/decisions/internals/index.md +46 -31
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +10 -10
- package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +30 -0
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +23 -19
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +2 -2
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +12 -12
- package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +22 -0
- package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +24 -0
- package/knowledge/decisions/internals/{the-actor-prompt-says-json-because-of-json-object-mode.md → the-virtual-user-prompt-says-json-because-of-json-object-mode.md} +4 -4
- package/knowledge/decisions/internals/{the-persona-runtime-is-exported-from-the-persona-entry-point.md → the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md} +8 -8
- package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +43 -0
- package/knowledge/decisions/internals/{actor-flow-drives-the-target-through-a-transport-seam.md → virtual-user-conversation-drives-the-target-through-a-transport-seam.md} +6 -6
- package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +25 -0
- package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +23 -0
- package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +30 -0
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +5 -5
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +2 -2
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +4 -4
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +1 -1
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +2 -2
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +1 -1
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +1 -1
- package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +26 -0
- package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +20 -0
- package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +23 -0
- package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +16 -0
- package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +26 -0
- package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +32 -0
- package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +27 -0
- package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +33 -0
- package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +25 -0
- package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +10 -5
- package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +27 -0
- package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +26 -0
- package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +25 -0
- package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +29 -0
- package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +25 -0
- package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +24 -0
- package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +29 -0
- package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +30 -0
- package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +38 -0
- package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +23 -0
- package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +27 -0
- package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +41 -0
- package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +25 -0
- package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +32 -0
- package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +20 -0
- package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +26 -0
- package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +33 -0
- package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +16 -0
- package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +26 -0
- package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +38 -0
- package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +31 -0
- package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +18 -0
- package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +32 -0
- package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +24 -0
- package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +26 -0
- package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +27 -0
- package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +25 -0
- package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +18 -0
- package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +29 -0
- package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +22 -0
- package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +29 -0
- package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +27 -0
- package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +25 -0
- package/knowledge/decisions/security/index.md +88 -24
- package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +21 -0
- package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +38 -0
- package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +18 -0
- package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +22 -0
- package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +26 -0
- package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +24 -0
- package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +35 -0
- package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +31 -0
- package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +22 -0
- package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +34 -0
- package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +26 -0
- package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +24 -0
- package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +16 -0
- package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +21 -0
- package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +24 -0
- package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +34 -0
- package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +16 -0
- package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +29 -0
- package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +23 -0
- package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +25 -0
- package/knowledge/decisions/security/{actor-flow-missing-approval-decisions-default-to-denied.md → virtual-user-conversation-missing-approval-decisions-default-to-denied.md} +7 -7
- package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +18 -0
- package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +25 -0
- package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +42 -0
- package/knowledge/decisions/security/{actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md → virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md} +10 -8
- package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +29 -0
- package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +18 -0
- package/knowledge/decisions/security/{workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md → workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md} +6 -6
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +5 -5
- package/knowledge/decisions/security/{workflow-actor-steps-always-use-the-real-transport.md → workflow-virtual-user-steps-always-use-the-real-transport.md} +11 -11
- package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +18 -0
- package/knowledge/index.md +0 -2
- package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +24 -0
- package/knowledge/questions/dev-quick-login-as-impersonation.md +25 -0
- package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +26 -0
- package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +27 -0
- package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +26 -0
- package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +26 -0
- package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +34 -0
- package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +20 -0
- package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +24 -0
- package/knowledge/questions/does-the-store-session-match-the-other-two.md +19 -0
- package/knowledge/questions/index.md +25 -2
- package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +21 -0
- package/knowledge/questions/live-scheduled-tests-may-write.md +19 -0
- package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +23 -0
- package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +32 -0
- package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +25 -0
- package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +23 -0
- package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +35 -0
- package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +23 -0
- package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +27 -0
- package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +26 -0
- package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +20 -0
- package/knowledge/questions/staging-impersonation-rules.md +27 -0
- package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +34 -0
- package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +20 -0
- package/knowledge/questions/what-an-impersonated-session-carries.md +22 -0
- package/package.json +2 -3
- package/src/public-surface.json +38 -47
- package/dist/services/persona-actor-secret.d.ts +0 -38
- package/dist/services/persona-actor-secret.js +0 -39
- package/dist/services/persona-sign-in.d.ts +0 -117
- package/dist/services/persona-sign-in.js +0 -154
- package/dist/wirings/actor-flow/index.d.ts +0 -2
- package/dist/wirings/actor-flow/run-conversation.d.ts +0 -36
- package/dist/wirings/persona/define-personas.d.ts +0 -32
- package/dist/wirings/persona/index.d.ts +0 -23
- package/dist/wirings/persona/index.js +0 -19
- package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +0 -23
- package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +0 -25
- package/knowledge/decisions/internals/validate-checks-personas-through-a-shared-module.md +0 -43
- package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +0 -31
- package/knowledge/decisions/security/an-actor-credential-is-derived-per-persona.md +0 -42
- package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +0 -26
- /package/dist/wirings/{actor-flow/actor-flow.types.js → virtual-user/conversation/conversation.types.js} +0 -0
- /package/dist/wirings/{actor-flow → virtual-user/conversation}/index.js +0 -0
- /package/dist/wirings/{persona/persona.types.js → virtual-user/virtual-user-declaration.types.js} +0 -0
- /package/dist/wirings/{persona/persona-mailbox.js → virtual-user/virtual-user-mailbox.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## 0.12.142
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- fdcc821: Fabric is gone from the open toolchain. The previous names are removed with no aliases.
|
|
6
|
+
|
|
7
|
+
The CLI group is `pikku cloud …` and the export is `@pikku/cli/cloud`. The project link is the `cloud` key of `pikku.config.json` (`cloud.projectId`), the CLI keeps its local state in `~/.pikkustudio` (run `pikku cloud login` again), and the project config file is `pikkustudio.config.json`.
|
|
8
|
+
|
|
9
|
+
Every environment variable drops the `FABRIC_` prefix for `PIKKUSTUDIO_` with the same suffix: `PIKKUSTUDIO_API_URL`, `PIKKUSTUDIO_PROJECT_ID`, `PIKKUSTUDIO_TOKEN`, `PIKKUSTUDIO_OPERATOR_TOKEN`, `PIKKUSTUDIO_AUTH_PUBLIC_KEY`, `PIKKUSTUDIO_STAGE_ID` and the rest. Rename them wherever you set them.
|
|
10
|
+
|
|
11
|
+
Wire ids: the operator sign-in route is `/sign-in/cloud`, the plugin and mode literal is `'cloud'`, the Better Auth plugin is `pikkuCloud`, its session field is `pikkustudioadmin`, and the signature header is `x-cloud-sig`. The cloud API calls are `getCloudLogs`, `getCloudLogsByStageKind`, `cloudCliProjects`, `cloudCliDeployments`, `providedByCloud` and `recordCloudAnalyticsEvents`. Addon packages are `@pikkustudio/*`, scaffolded files live under `scaffold/cloud` and `__cloud_*__`, and the API hosts are the `pikkustudio.app` and `pikkustudio.dev` domains.
|
|
12
|
+
|
|
13
|
+
`pikku skills install --fabric` is `--cloud`, the install group is `cloud`, and the skills are `pikku-cloud`, `pikku-cloud-debug`, `pikku-admin-to-cloud` and `pikku-blueprint-to-cloud`.
|
|
14
|
+
|
|
15
|
+
The stale analytics forwarder copies are removed from the online-shop example and the starter template.
|
|
16
|
+
|
|
17
|
+
The sealed-box salt stays `pikkufabric/sealed-box/v1`: it is a cryptographic constant that already-sealed secrets depend on.
|
|
18
|
+
|
|
19
|
+
- 33b102d: Virtual users now have one name everywhere. The id column of `virtual_user_run` and `virtual_user_schedule` is `virtual_user_id` (a migration renames it in place), the CLI group is `pikku virtual-user …`, and the declarations and imports live under `@pikku/core/virtual-user`. The previous names are removed with no aliases.
|
|
20
|
+
|
|
21
|
+
The default virtual user email domain is now `virtualuser.invalid`: apps that rely on the default domain get new accounts at the next provisioning (`pikku virtual-user sync`, deploy, or `pikku dev` start), and the old rows stay unused.
|
|
22
|
+
|
|
23
|
+
The sign-in surface carries the same name. The route is `/sign-in/virtual-user`, the environment variables are `PIKKU_ALLOW_VIRTUAL_USER_SIGN_IN` and the `PIKKU_DEV_VIRTUAL_USER_SIGN_IN` / `VITE_*` equivalents, the Better Auth plugin is `pikkuVirtualUser`, the scenario step option and wire member are `virtualUser` and `virtualUsers`, and the Better Auth user flag column is `virtual_user`. Rename the environment variables wherever you set them, and add a migration that renames the flag column on the `user` table. Nothing is aliased.
|
|
24
|
+
|
|
25
|
+
The conversation runner is now `@pikku/core/virtual-user/conversation`, replacing the old `-flow` subpath. Update the import; the old subpath is gone.
|
|
26
|
+
|
|
27
|
+
- 6a25c70: Virtual users no longer run against production. Starting a run, and enabling a schedule, is refused with a 403 in a production environment for every disposition, including `accountable`, which was the one disposition production used to accept. Turning a schedule off or editing a disabled one is still allowed, so a leftover schedule can be stopped.
|
|
28
|
+
- a084c3b: Virtual users sign themselves in. A scheduled run signs in from inside the app through a server-only Better Auth endpoint, then drives the app over HTTP with the cookie. Outside callers (`pikku dev`, `pikku scenario run`, `pikku virtual-user run` and `rpc`, `pikku pages screenshot --as`, the Playwright provider) present one signed, short-lived, single-use EdDSA statement, which the app checks against `VIRTUAL_USER_VERIFY_KEY`; `pikku dev` generates the key pair, and a deployed stage's deployer holds `VIRTUAL_USER_SIGNING_KEY`. `@pikku/jose` gains `JoseVirtualUserStatementVerifier` and `@pikku/better-auth` takes `verifyKey`. Removed with no aliases: the operator token and `OperatorSignIn`, derived per-virtual-user secrets, `SCENARIO_VIRTUAL_USER_SECRET`, `PIKKU_VIRTUAL_USER_SECRETS`, `pikku virtual-user secret`, and `wireVirtualUserSignIn`. In production neither sign-in endpoint is registered.
|
|
29
|
+
|
|
30
|
+
The scenario cookie jar moved to `services` and `createCookieJar` is exported from `@pikku/core/virtual-user`, which removes the wire-to-wire import cycles; `VirtualUserSignIn.headers` is now optional.
|
|
31
|
+
|
|
32
|
+
Migration for apps: pass `verifyKey: await variables.get('VIRTUAL_USER_VERIFY_KEY')` to `pikkuVirtualUser` instead of `secret`, declare that variable as optional, delete any `SCENARIO_VIRTUAL_USER_SECRET` secret and any `wireVirtualUserSignIn` call, and stop passing `secret` or `operator` to `createHttpVirtualUsers`. A stage that must run scenarios still opts in with `PIKKU_ALLOW_VIRTUAL_USER_SIGN_IN`.
|
|
33
|
+
|
|
1
34
|
## 0.12.141
|
|
2
35
|
|
|
3
36
|
### Patch Changes
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -118,7 +118,7 @@ export declare class AIProviderAuthError extends PikkuError {
|
|
|
118
118
|
*
|
|
119
119
|
* System roles ship with the product: the console may show and grant them, but
|
|
120
120
|
* renaming, re-scoping or deleting one would let a UI action silently change
|
|
121
|
-
* what a declared
|
|
121
|
+
* what a declared virtual user means, and what every scenario written against that
|
|
122
122
|
* role is actually testing.
|
|
123
123
|
* @group Error
|
|
124
124
|
*/
|
package/dist/errors/errors.js
CHANGED
|
@@ -314,7 +314,7 @@ addError(AIProviderAuthError, {
|
|
|
314
314
|
*
|
|
315
315
|
* System roles ship with the product: the console may show and grant them, but
|
|
316
316
|
* renaming, re-scoping or deleting one would let a UI action silently change
|
|
317
|
-
* what a declared
|
|
317
|
+
* what a declared virtual user means, and what every scenario written against that
|
|
318
318
|
* role is actually testing.
|
|
319
319
|
* @group Error
|
|
320
320
|
*/
|
|
@@ -80,17 +80,17 @@ export type FunctionRuntimeMeta = {
|
|
|
80
80
|
*/
|
|
81
81
|
scenarioStepSurfaces?: ScenarioSurface[];
|
|
82
82
|
/**
|
|
83
|
-
* Scenario steps only: this step runs as a
|
|
84
|
-
* pass one and the runner injects it as `wire.
|
|
83
|
+
* Scenario steps only: this step runs as a virtual user, so every call site must
|
|
84
|
+
* pass one and the runner injects it as `wire.virtualUser`.
|
|
85
85
|
*
|
|
86
|
-
* Declared by `
|
|
86
|
+
* Declared by `virtualUser: true`, or implied by a `browser` binding — a window is
|
|
87
87
|
* opened as somebody. Absent on a step with nobody to be: an assertion over
|
|
88
88
|
* what an earlier step returned, or one posting credentials precisely because
|
|
89
|
-
* it must not reuse
|
|
89
|
+
* it must not reuse a virtual user's session.
|
|
90
90
|
*/
|
|
91
|
-
|
|
91
|
+
scenarioStepRequiresVirtualUser?: boolean;
|
|
92
92
|
/**
|
|
93
|
-
* Scenario steps only: who acts. Absent means `
|
|
93
|
+
* Scenario steps only: who acts. Absent means `virtualUser` — the ordinary step,
|
|
94
94
|
* and the only kind that existed before the other two.
|
|
95
95
|
*
|
|
96
96
|
* A `platform` or `addon` step is the app or a third-party system acting, and
|
|
@@ -111,8 +111,8 @@ export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any,
|
|
|
111
111
|
* and report how much of the flow each surface actually covers.
|
|
112
112
|
*/
|
|
113
113
|
surfaces?: ScenarioSurface[];
|
|
114
|
-
/** Scenario steps only, and set by the definer rather than by hand: this step needs a
|
|
115
|
-
|
|
114
|
+
/** Scenario steps only, and set by the definer rather than by hand: this step needs a virtual user, so the runner injects `wire.virtualUser`. */
|
|
115
|
+
requiresVirtualUser?: boolean;
|
|
116
116
|
/**
|
|
117
117
|
* Records every call in the audit log. `transactional` durability writes the
|
|
118
118
|
* entry in the same transaction as the work, so the two cannot disagree;
|
|
@@ -13,10 +13,10 @@ export type ResolvedAuditConfig = {
|
|
|
13
13
|
/**
|
|
14
14
|
* Who an event happened under.
|
|
15
15
|
*
|
|
16
|
-
* A user, not an "
|
|
17
|
-
* drives, flagged `
|
|
18
|
-
* audited events are caused by ordinary customers. Naming this `
|
|
19
|
-
* synthetic case unsayable — `
|
|
16
|
+
* A user, not an "virtualUser": in pikku a virtual user is a synthetic person a scenario
|
|
17
|
+
* drives, flagged `virtualUser` on the user row, and the overwhelming majority of
|
|
18
|
+
* audited events are caused by ordinary customers. Naming this `virtualUser` made the
|
|
19
|
+
* synthetic case unsayable — `virtualUser.virtualUser === true` — and implied every
|
|
20
20
|
* recorded action was a test.
|
|
21
21
|
*
|
|
22
22
|
* `pikkuUserId` is the identity pikku resolves for every wire, so it is the one
|
|
@@ -88,10 +88,10 @@ export interface FeatureFlagStore extends FeatureFlagSource {
|
|
|
88
88
|
* every flag to render a board would grow with the wrong number.
|
|
89
89
|
*/
|
|
90
90
|
listOverrides(key: string): Promise<FlagOverrideRow[]>;
|
|
91
|
-
setEnabled(key: string, enabled: boolean,
|
|
91
|
+
setEnabled(key: string, enabled: boolean, virtualUser?: string, note?: string): Promise<void>;
|
|
92
92
|
/** `percent` is 0–100, or null to remove the rollout constraint. */
|
|
93
|
-
setRollout(key: string, percent: number | null,
|
|
94
|
-
setOverride(key: string, subject: FlagSubject, enabled: boolean,
|
|
93
|
+
setRollout(key: string, percent: number | null, virtualUser?: string): Promise<void>;
|
|
94
|
+
setOverride(key: string, subject: FlagSubject, enabled: boolean, virtualUser?: string): Promise<void>;
|
|
95
95
|
clearOverride(key: string, subject: FlagSubject): Promise<void>;
|
|
96
96
|
/** Flags in the store with no declaration left in code; powers `pikku flags audit`. */
|
|
97
97
|
findStaleFlags(): Promise<string[]>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ConverseOptions,
|
|
3
|
-
import { type
|
|
4
|
-
export interface
|
|
1
|
+
import type { ScenarioVirtualUser, ResolvedVirtualUser, ScenarioVirtualUsers, ScenarioInvokeOptions, ScenarioHttpResponse } from './virtual-users-service.js';
|
|
2
|
+
import type { ConverseOptions, ConversationVerdict } from '../wirings/virtual-user/conversation/conversation.types.js';
|
|
3
|
+
import { type VirtualUserSignIn } from './virtual-user-sign-in.js';
|
|
4
|
+
export interface HttpVirtualUsersConfig {
|
|
5
5
|
/**
|
|
6
6
|
* Base API URL of the target app, INCLUDING the HTTP prefix — e.g.
|
|
7
7
|
* `https://app.example.com/api` or `http://localhost:4000/api`. Sign-in is
|
|
@@ -10,39 +10,21 @@ export interface HttpPersonasConfig {
|
|
|
10
10
|
*/
|
|
11
11
|
apiUrl: string;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `actor: true`, and a derived credential only ever works for the one address
|
|
16
|
-
* it was derived for.
|
|
17
|
-
*
|
|
18
|
-
* Pass an {@link ActorSecretResolver} instead to drive personas whose
|
|
19
|
-
* credentials were minted elsewhere — a caller entitled to one persona then
|
|
20
|
-
* never holds the root.
|
|
21
|
-
*
|
|
22
|
-
* The local-development credential. A deployed stage has none, and passes
|
|
23
|
-
* {@link HttpPersonasConfig.operator} instead.
|
|
24
|
-
*/
|
|
25
|
-
secret?: string | ActorSecretResolver;
|
|
26
|
-
/**
|
|
27
|
-
* Fabric operator credentials, for signing personas into a DEPLOYED stage.
|
|
28
|
-
*
|
|
29
|
-
* Mutually exclusive with {@link HttpPersonasConfig.secret}: the operator
|
|
30
|
-
* path acts as the persona through an admin session rather than logging in as
|
|
31
|
-
* them, so no test credential has to exist on the target at all.
|
|
13
|
+
* How each virtual user obtains a session: {@link inProcessSignIn} from inside
|
|
14
|
+
* the app, {@link statementSignIn} from outside it.
|
|
32
15
|
*/
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
|
|
16
|
+
signIn: VirtualUserSignIn;
|
|
17
|
+
/** Virtual user id → the declaration with its address filled in. */
|
|
18
|
+
virtualUsers: Record<string, ResolvedVirtualUser>;
|
|
36
19
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* {@link OperatorSignInOptions.signInPath} overrides it.
|
|
20
|
+
* The sign-in path, when the app mounts auth somewhere other than `/auth`.
|
|
21
|
+
* Only the mount is used here, to find `get-session`; signing in itself is
|
|
22
|
+
* the job of {@link HttpVirtualUsersConfig.signIn}.
|
|
41
23
|
*/
|
|
42
24
|
signInPath?: string;
|
|
43
25
|
/**
|
|
44
26
|
* Where the session (and its roles) is read back. Defaults to `get-session`
|
|
45
|
-
* under the same auth mount as {@link
|
|
27
|
+
* under the same auth mount as {@link HttpVirtualUsersConfig.signInPath}, so an
|
|
46
28
|
* app that moved auth under `/api` moves this with it and does not have to
|
|
47
29
|
* say so twice.
|
|
48
30
|
*/
|
|
@@ -57,28 +39,24 @@ export interface HttpPersonasConfig {
|
|
|
57
39
|
* on scopes that column is a projection rather than the model — it exists so
|
|
58
40
|
* better-auth's own admin endpoints have something to read, is written by
|
|
59
41
|
* whatever keeps it in step, and is absent entirely from an app that declares
|
|
60
|
-
* no such field. A
|
|
42
|
+
* no such field. A virtual user verified against it is verified against a copy.
|
|
61
43
|
*/
|
|
62
44
|
rolesRpc?: string | false;
|
|
63
45
|
/**
|
|
64
|
-
* Default model a
|
|
46
|
+
* Default model a virtual user thinks with when `converse(...)` is called without
|
|
65
47
|
* an explicit `model`. Its own turns/approvals/evaluation run in-process via
|
|
66
48
|
* the configured `agentRunner`.
|
|
67
49
|
*/
|
|
68
50
|
model?: string;
|
|
69
51
|
}
|
|
70
52
|
/**
|
|
71
|
-
* Default HTTP-backed
|
|
53
|
+
* Default HTTP-backed virtual user. Signs in lazily on first invoke, holds the
|
|
72
54
|
* session cookies for its lifetime, and re-logs-in once on a 401 mid-run (long
|
|
73
55
|
* health-check runs can outlive a session).
|
|
74
|
-
*
|
|
75
|
-
* How it signs in depends on the target, and the two ways are not
|
|
76
|
-
* interchangeable — see {@link ActorSignIn} for local development and
|
|
77
|
-
* {@link OperatorSignIn} for a deployed stage.
|
|
78
56
|
*/
|
|
79
|
-
export declare class
|
|
57
|
+
export declare class HttpVirtualUser implements ScenarioVirtualUser {
|
|
80
58
|
readonly name: string;
|
|
81
|
-
private
|
|
59
|
+
private virtualUser;
|
|
82
60
|
private config;
|
|
83
61
|
private jar;
|
|
84
62
|
/**
|
|
@@ -89,15 +67,15 @@ export declare class HttpPersona implements ScenarioPersona {
|
|
|
89
67
|
*/
|
|
90
68
|
private signedIn;
|
|
91
69
|
private signIn;
|
|
92
|
-
constructor(name: string,
|
|
70
|
+
constructor(name: string, virtualUser: ResolvedVirtualUser, config: HttpVirtualUsersConfig);
|
|
93
71
|
get email(): string;
|
|
94
72
|
invoke(rpcName: string, data: unknown): Promise<unknown>;
|
|
95
73
|
invokeRaw(rpcName: string, data: unknown, options?: ScenarioInvokeOptions): Promise<ScenarioHttpResponse>;
|
|
96
|
-
converse(options: ConverseOptions): Promise<
|
|
74
|
+
converse(options: ConverseOptions): Promise<ConversationVerdict>;
|
|
97
75
|
/**
|
|
98
76
|
* The roles the stage says this session holds.
|
|
99
77
|
*
|
|
100
|
-
* {@link
|
|
78
|
+
* {@link HttpVirtualUsersConfig.rolesRpc} first, then better-auth's
|
|
101
79
|
* `get-session` — where its admin plugin puts `role` on the user, as a
|
|
102
80
|
* comma-separated list. A target that answers neither returns `null` rather
|
|
103
81
|
* than an empty list, because "this stage does not report roles" and "this
|
|
@@ -112,7 +90,7 @@ export declare class HttpPersona implements ScenarioPersona {
|
|
|
112
90
|
private rolesFromRpc;
|
|
113
91
|
private rolesFromSession;
|
|
114
92
|
/**
|
|
115
|
-
* Start/continue the target agent's run over HTTP as this
|
|
93
|
+
* Start/continue the target agent's run over HTTP as this virtual user.
|
|
116
94
|
*
|
|
117
95
|
* The SSE route, not the plain one. `POST /rpc/agent/:name` buffers the whole
|
|
118
96
|
* run before it sends a single byte, so a run longer than the client's
|
|
@@ -134,7 +112,7 @@ export declare class HttpPersona implements ScenarioPersona {
|
|
|
134
112
|
private login;
|
|
135
113
|
}
|
|
136
114
|
/**
|
|
137
|
-
* Build the injected `
|
|
138
|
-
* HTTP
|
|
115
|
+
* Build the injected `virtualUsers` service from the declared virtual users: id → lazy
|
|
116
|
+
* HTTP virtual user. Wire the result as the `virtualUsers` singleton service.
|
|
139
117
|
*/
|
|
140
|
-
export declare function
|
|
118
|
+
export declare function createHttpVirtualUsers(config: HttpVirtualUsersConfig): ScenarioVirtualUsers;
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import { readScenarioHttpResponse } from './
|
|
2
|
-
import { runConversation } from '../wirings/
|
|
3
|
-
import { createCookieJar, } from '
|
|
4
|
-
import {
|
|
1
|
+
import { readScenarioHttpResponse } from './virtual-users-service.js';
|
|
2
|
+
import { runConversation } from '../wirings/virtual-user/conversation/run-conversation.js';
|
|
3
|
+
import { createCookieJar, } from './scenario-cookie-jar.js';
|
|
4
|
+
import { authMount } from './virtual-user-sign-in.js';
|
|
5
5
|
import { getSingletonServices } from '../pikku-state.js';
|
|
6
6
|
import { AIProviderNotConfiguredError } from '../errors/errors.js';
|
|
7
7
|
/**
|
|
8
|
-
* Default HTTP-backed
|
|
8
|
+
* Default HTTP-backed virtual user. Signs in lazily on first invoke, holds the
|
|
9
9
|
* session cookies for its lifetime, and re-logs-in once on a 401 mid-run (long
|
|
10
10
|
* health-check runs can outlive a session).
|
|
11
|
-
*
|
|
12
|
-
* How it signs in depends on the target, and the two ways are not
|
|
13
|
-
* interchangeable — see {@link ActorSignIn} for local development and
|
|
14
|
-
* {@link OperatorSignIn} for a deployed stage.
|
|
15
11
|
*/
|
|
16
|
-
export class
|
|
12
|
+
export class HttpVirtualUser {
|
|
17
13
|
name;
|
|
18
|
-
|
|
14
|
+
virtualUser;
|
|
19
15
|
config;
|
|
20
16
|
jar;
|
|
21
17
|
/**
|
|
@@ -26,29 +22,15 @@ export class HttpPersona {
|
|
|
26
22
|
*/
|
|
27
23
|
signedIn = false;
|
|
28
24
|
signIn;
|
|
29
|
-
constructor(name,
|
|
25
|
+
constructor(name, virtualUser, config) {
|
|
30
26
|
this.name = name;
|
|
31
|
-
this.
|
|
27
|
+
this.virtualUser = virtualUser;
|
|
32
28
|
this.config = config;
|
|
33
29
|
this.jar = createCookieJar(config.apiUrl);
|
|
34
|
-
|
|
35
|
-
this.signIn = new OperatorSignIn(config.apiUrl, {
|
|
36
|
-
...config.operator,
|
|
37
|
-
signInPath: config.operator.signInPath ??
|
|
38
|
-
(authMount(config.signInPath)
|
|
39
|
-
? `${authMount(config.signInPath)}/sign-in/fabric`
|
|
40
|
-
: undefined),
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
else if (config.secret) {
|
|
44
|
-
this.signIn = new ActorSignIn(config.apiUrl, config.secret, config.signInPath ?? '/auth/sign-in/actor');
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
throw new Error(`[scenario] persona '${name}' has no way to sign in — set 'secret' for a dev target or 'operator' for a deployed one`);
|
|
48
|
-
}
|
|
30
|
+
this.signIn = config.signIn;
|
|
49
31
|
}
|
|
50
32
|
get email() {
|
|
51
|
-
return this.
|
|
33
|
+
return this.virtualUser.email;
|
|
52
34
|
}
|
|
53
35
|
async invoke(rpcName, data) {
|
|
54
36
|
const res = await this.invokeRaw(rpcName, data);
|
|
@@ -78,20 +60,20 @@ export class HttpPersona {
|
|
|
78
60
|
// Signed in here rather than left to postAgent's 401 retry, which a public
|
|
79
61
|
// agent route never triggers. An unowned thread is minted under a fresh
|
|
80
62
|
// anonymous id per request, so turn one succeeds and turn two is refused as
|
|
81
|
-
// somebody else's — and a
|
|
63
|
+
// somebody else's — and a virtual user is a real account with real credentials,
|
|
82
64
|
// so there is no case where conversing as nobody is the intent.
|
|
83
65
|
if (!this.signedIn) {
|
|
84
66
|
await this.login();
|
|
85
67
|
}
|
|
86
68
|
const model = options.model ?? this.config.model;
|
|
87
69
|
if (!model) {
|
|
88
|
-
throw new Error(`[scenario]
|
|
70
|
+
throw new Error(`[scenario] virtual user '${this.name}' converse needs a model — pass options.model or set 'model' on the virtual users service`);
|
|
89
71
|
}
|
|
90
72
|
const threadId = globalThis.crypto.randomUUID();
|
|
91
|
-
const resourceId = `
|
|
73
|
+
const resourceId = `virtualUser:${this.name}`;
|
|
92
74
|
return runConversation({
|
|
93
|
-
|
|
94
|
-
|
|
75
|
+
virtualUser: this.virtualUser,
|
|
76
|
+
virtualUserId: this.name,
|
|
95
77
|
agentName: options.agent,
|
|
96
78
|
task: options.task,
|
|
97
79
|
evaluate: options.evaluate,
|
|
@@ -108,7 +90,7 @@ export class HttpPersona {
|
|
|
108
90
|
/**
|
|
109
91
|
* The roles the stage says this session holds.
|
|
110
92
|
*
|
|
111
|
-
* {@link
|
|
93
|
+
* {@link HttpVirtualUsersConfig.rolesRpc} first, then better-auth's
|
|
112
94
|
* `get-session` — where its admin plugin puts `role` on the user, as a
|
|
113
95
|
* comma-separated list. A target that answers neither returns `null` rather
|
|
114
96
|
* than an empty list, because "this stage does not report roles" and "this
|
|
@@ -148,11 +130,9 @@ export class HttpPersona {
|
|
|
148
130
|
return roles.filter((name) => typeof name === 'string');
|
|
149
131
|
}
|
|
150
132
|
async rolesFromSession() {
|
|
151
|
-
const mount = authMount(this.config.
|
|
133
|
+
const mount = authMount(this.config.signInPath);
|
|
152
134
|
const sessionPath = this.config.sessionPath ?? `${mount ?? '/auth'}/get-session`;
|
|
153
|
-
const res = await this.jar.fetch(`${this.config.apiUrl}${sessionPath}
|
|
154
|
-
headers: this.signIn.headers(),
|
|
155
|
-
});
|
|
135
|
+
const res = await this.jar.fetch(`${this.config.apiUrl}${sessionPath}`);
|
|
156
136
|
if (!res.ok) {
|
|
157
137
|
return null;
|
|
158
138
|
}
|
|
@@ -183,7 +163,7 @@ export class HttpPersona {
|
|
|
183
163
|
return user ? [] : null;
|
|
184
164
|
}
|
|
185
165
|
/**
|
|
186
|
-
* Start/continue the target agent's run over HTTP as this
|
|
166
|
+
* Start/continue the target agent's run over HTTP as this virtual user.
|
|
187
167
|
*
|
|
188
168
|
* The SSE route, not the plain one. `POST /rpc/agent/:name` buffers the whole
|
|
189
169
|
* run before it sends a single byte, so a run longer than the client's
|
|
@@ -216,10 +196,7 @@ export class HttpPersona {
|
|
|
216
196
|
const url = `${this.config.apiUrl}${rpcPath}/${subPath}`;
|
|
217
197
|
const send = () => this.jar.fetch(url, {
|
|
218
198
|
method: 'POST',
|
|
219
|
-
headers: {
|
|
220
|
-
'content-type': 'application/json',
|
|
221
|
-
...this.signIn.headers(),
|
|
222
|
-
},
|
|
199
|
+
headers: { 'content-type': 'application/json' },
|
|
223
200
|
body: JSON.stringify(body),
|
|
224
201
|
});
|
|
225
202
|
let res = await send();
|
|
@@ -247,7 +224,6 @@ export class HttpPersona {
|
|
|
247
224
|
method: 'POST',
|
|
248
225
|
headers: {
|
|
249
226
|
'content-type': 'application/json',
|
|
250
|
-
...this.signIn.headers(),
|
|
251
227
|
...extraHeaders,
|
|
252
228
|
},
|
|
253
229
|
body: JSON.stringify({ data }),
|
|
@@ -259,7 +235,7 @@ export class HttpPersona {
|
|
|
259
235
|
this.signedIn = false;
|
|
260
236
|
}
|
|
261
237
|
async login() {
|
|
262
|
-
await this.signIn.login(this.jar, this.
|
|
238
|
+
await this.signIn.login(this.jar, this.virtualUser);
|
|
263
239
|
this.signedIn = true;
|
|
264
240
|
}
|
|
265
241
|
}
|
|
@@ -358,13 +334,13 @@ function normalizeAgentReply(raw) {
|
|
|
358
334
|
};
|
|
359
335
|
}
|
|
360
336
|
/**
|
|
361
|
-
* Build the injected `
|
|
362
|
-
* HTTP
|
|
337
|
+
* Build the injected `virtualUsers` service from the declared virtual users: id → lazy
|
|
338
|
+
* HTTP virtual user. Wire the result as the `virtualUsers` singleton service.
|
|
363
339
|
*/
|
|
364
|
-
export function
|
|
365
|
-
const
|
|
366
|
-
for (const [id,
|
|
367
|
-
|
|
340
|
+
export function createHttpVirtualUsers(config) {
|
|
341
|
+
const virtualUsers = {};
|
|
342
|
+
for (const [id, virtualUser] of Object.entries(config.virtualUsers)) {
|
|
343
|
+
virtualUsers[id] = new HttpVirtualUser(id, virtualUser, config);
|
|
368
344
|
}
|
|
369
|
-
return
|
|
345
|
+
return virtualUsers;
|
|
370
346
|
}
|
package/dist/services/index.d.ts
CHANGED
|
@@ -23,12 +23,12 @@ export { InMemoryLeaseService } from './in-memory-lease-service.js';
|
|
|
23
23
|
export { InMemoryAgentRunStateService } from './in-memory-agent-run-state-service.js';
|
|
24
24
|
export { LocalGatewayService } from './local-gateway-service.js';
|
|
25
25
|
export type { ContentService, ContentVisibility, GetDownloadURLArgs, SignContentKeyArgs, SignURLArgs, GetUploadURLArgs, UploadURLResult, BucketKeyArgs, WriteFileArgs, CopyFileArgs, } from './content-service.js';
|
|
26
|
-
export type {
|
|
26
|
+
export type { ScenarioVirtualUser, ResolvedVirtualUser, ScenarioVirtualUsers, } from './virtual-users-service.js';
|
|
27
27
|
export type { JWTService } from './jwt-service.js';
|
|
28
28
|
export type { EmailAttachment, EmailService, SendEmailInput, SendEmailResult, SendHTMLEmailInput, SendTemplateEmailInput, SendTextEmailInput, } from './email-service.js';
|
|
29
29
|
export { renderEmail, type EmailAssets, type EmailTemplateAssets, type EmailTemplateHashes, type RenderEmailRequest, type RenderedEmailResult, } from './email-template.js';
|
|
30
30
|
export { DEFAULT_WEBHOOK_RETRIES, PIKKU_OUTGOING_WEBHOOK_QUEUE_NAME, WebhookService, type SendWebhookInput, type SendWebhookResult, type WebhookAttemptResult, type WebhookDeliveryRecord, type WebhookDeliveryWithAttempts, type WebhookJobData, type WebhookServiceConfig, } from './webhook-service.js';
|
|
31
|
-
export {
|
|
31
|
+
export { VIRTUAL_USER_IN_PROCESS_ENDPOINT, VIRTUAL_USER_STATEMENT_ALGORITHM, VIRTUAL_USER_STATEMENT_MAX_TTL_SECONDS, VIRTUAL_USER_STATEMENT_TTL_SECONDS, VIRTUAL_USER_SIGNING_KEY_VARIABLE, VIRTUAL_USER_VERIFY_KEY_VARIABLE, VirtualUserStatementError, type VirtualUserStatementVerifier, } from './virtual-user-statement.js';
|
|
32
32
|
export type { Logger } from './logger.js';
|
|
33
33
|
export type { SecretService, SecretValues } from './secret-service.js';
|
|
34
34
|
export type { VariablesService } from './variables-service.js';
|
package/dist/services/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export { InMemoryAgentRunStateService } from './in-memory-agent-run-state-servic
|
|
|
24
24
|
export { LocalGatewayService } from './local-gateway-service.js';
|
|
25
25
|
export { renderEmail, } from './email-template.js';
|
|
26
26
|
export { DEFAULT_WEBHOOK_RETRIES, PIKKU_OUTGOING_WEBHOOK_QUEUE_NAME, WebhookService, } from './webhook-service.js';
|
|
27
|
-
export {
|
|
27
|
+
export { VIRTUAL_USER_IN_PROCESS_ENDPOINT, VIRTUAL_USER_STATEMENT_ALGORITHM, VIRTUAL_USER_STATEMENT_MAX_TTL_SECONDS, VIRTUAL_USER_STATEMENT_TTL_SECONDS, VIRTUAL_USER_SIGNING_KEY_VARIABLE, VIRTUAL_USER_VERIFY_KEY_VARIABLE, VirtualUserStatementError, } from './virtual-user-statement.js';
|
|
28
28
|
export { SchedulerService } from './scheduler-service.js';
|
|
29
29
|
export { TypedCredentialService } from './typed-credential-service.js';
|
|
30
30
|
export { NoopAuditService, createInvocationAudit } from './audit-service.js';
|
|
@@ -7,7 +7,7 @@ import type { CLIMeta } from '../wirings/cli/cli.types.js';
|
|
|
7
7
|
import type { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '../wirings/mcp/mcp.types.js';
|
|
8
8
|
import type { WorkflowsMeta } from '../wirings/workflow/workflow.types.js';
|
|
9
9
|
import type { FeaturesMeta } from '../wirings/workflow/scenario.types.js';
|
|
10
|
-
import type {
|
|
10
|
+
import type { ResolvedVirtualUser } from './virtual-users-service.js';
|
|
11
11
|
import type { SystemRoleDefinitionsMeta } from '../wirings/role/role.types.js';
|
|
12
12
|
import type { FeatureFlagDefinitionsMeta } from '../wirings/flag/flag.types.js';
|
|
13
13
|
import type { ScopeDefinitionsMeta } from '../wirings/scope/scope.types.js';
|
|
@@ -147,12 +147,12 @@ export interface MetaService {
|
|
|
147
147
|
getGatewayMeta(): Promise<GatewaysMeta>;
|
|
148
148
|
getRpcMeta(): Promise<RPCMetaRecord>;
|
|
149
149
|
getWorkflowMeta(): Promise<WorkflowsMeta>;
|
|
150
|
-
|
|
150
|
+
getVirtualUsersMeta(): Promise<Record<string, ResolvedVirtualUser>>;
|
|
151
151
|
/**
|
|
152
152
|
* The roles declared with `defineSystemRole`, keyed by name.
|
|
153
153
|
*
|
|
154
|
-
* A
|
|
155
|
-
*
|
|
154
|
+
* A virtual user declares roles; a function checks scopes. Anything showing what a
|
|
155
|
+
* virtual user can reach — the console's virtual user page, a run's catalogue — needs
|
|
156
156
|
* this to get from one to the other, and needs it to be the same expansion the
|
|
157
157
|
* seed granted from rather than a second one.
|
|
158
158
|
*/
|
|
@@ -206,7 +206,7 @@ export declare class LocalMetaService implements MetaService {
|
|
|
206
206
|
private gatewayMetaCache;
|
|
207
207
|
private rpcMetaCache;
|
|
208
208
|
private workflowMetaCache;
|
|
209
|
-
private
|
|
209
|
+
private virtualUsersMetaCache;
|
|
210
210
|
private systemRolesMetaCache;
|
|
211
211
|
private scopesMetaCache;
|
|
212
212
|
private featureFlagsMetaCache;
|
|
@@ -244,7 +244,7 @@ export declare class LocalMetaService implements MetaService {
|
|
|
244
244
|
getRpcMeta(): Promise<RPCMetaRecord>;
|
|
245
245
|
private readWorkflowMetaDir;
|
|
246
246
|
getWorkflowMeta(): Promise<WorkflowsMeta>;
|
|
247
|
-
|
|
247
|
+
getVirtualUsersMeta(): Promise<Record<string, ResolvedVirtualUser>>;
|
|
248
248
|
getSystemRolesMeta(): Promise<SystemRoleDefinitionsMeta>;
|
|
249
249
|
getScopesMeta(): Promise<ScopeDefinitionsMeta>;
|
|
250
250
|
getFeatureFlagsMeta(): Promise<FeatureFlagDefinitionsMeta>;
|
|
@@ -14,7 +14,7 @@ export class LocalMetaService {
|
|
|
14
14
|
gatewayMetaCache = null;
|
|
15
15
|
rpcMetaCache = null;
|
|
16
16
|
workflowMetaCache = null;
|
|
17
|
-
|
|
17
|
+
virtualUsersMetaCache = null;
|
|
18
18
|
systemRolesMetaCache = null;
|
|
19
19
|
scopesMetaCache = null;
|
|
20
20
|
featureFlagsMetaCache = null;
|
|
@@ -114,7 +114,7 @@ export class LocalMetaService {
|
|
|
114
114
|
this.gatewayMetaCache = null;
|
|
115
115
|
this.rpcMetaCache = null;
|
|
116
116
|
this.workflowMetaCache = null;
|
|
117
|
-
this.
|
|
117
|
+
this.virtualUsersMetaCache = null;
|
|
118
118
|
this.systemRolesMetaCache = null;
|
|
119
119
|
this.scopesMetaCache = null;
|
|
120
120
|
this.featureFlagsMetaCache = null;
|
|
@@ -265,12 +265,12 @@ export class LocalMetaService {
|
|
|
265
265
|
return this.workflowMetaCache;
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
-
async
|
|
269
|
-
if (this.
|
|
270
|
-
return this.
|
|
271
|
-
const content = await this.readFile('workflow/
|
|
272
|
-
this.
|
|
273
|
-
return this.
|
|
268
|
+
async getVirtualUsersMeta() {
|
|
269
|
+
if (this.virtualUsersMetaCache)
|
|
270
|
+
return this.virtualUsersMetaCache;
|
|
271
|
+
const content = await this.readFile('workflow/virtual-users.gen.json');
|
|
272
|
+
this.virtualUsersMetaCache = content ? JSON.parse(content) : {};
|
|
273
|
+
return this.virtualUsersMetaCache;
|
|
274
274
|
}
|
|
275
275
|
async getSystemRolesMeta() {
|
|
276
276
|
if (this.systemRolesMetaCache)
|
|
@@ -7,7 +7,24 @@
|
|
|
7
7
|
export const createCookieJar = (apiUrl) => {
|
|
8
8
|
const jar = new Map();
|
|
9
9
|
const origin = new URL(apiUrl).origin;
|
|
10
|
+
const absorb = (setCookies) => {
|
|
11
|
+
for (const raw of setCookies) {
|
|
12
|
+
const [pair] = raw.split(';');
|
|
13
|
+
const separator = pair.indexOf('=');
|
|
14
|
+
if (separator > 0) {
|
|
15
|
+
const name = pair.slice(0, separator);
|
|
16
|
+
const value = pair.slice(separator + 1);
|
|
17
|
+
if (value) {
|
|
18
|
+
jar.set(name, value);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
jar.delete(name);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
10
26
|
return {
|
|
27
|
+
absorb,
|
|
11
28
|
fetch: async (input, init) => {
|
|
12
29
|
const headers = new Headers(init?.headers);
|
|
13
30
|
headers.set('origin', origin);
|
|
@@ -26,20 +43,7 @@ export const createCookieJar = (apiUrl) => {
|
|
|
26
43
|
headers.set('cookie', [caller, ...held].filter(Boolean).join('; '));
|
|
27
44
|
}
|
|
28
45
|
const response = await fetch(input, { ...init, headers });
|
|
29
|
-
|
|
30
|
-
const [pair] = raw.split(';');
|
|
31
|
-
const separator = pair.indexOf('=');
|
|
32
|
-
if (separator > 0) {
|
|
33
|
-
const name = pair.slice(0, separator);
|
|
34
|
-
const value = pair.slice(separator + 1);
|
|
35
|
-
if (value) {
|
|
36
|
-
jar.set(name, value);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
jar.delete(name);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
46
|
+
absorb(response.headers.getSetCookie());
|
|
43
47
|
return response;
|
|
44
48
|
},
|
|
45
49
|
clear: () => jar.clear(),
|
|
@@ -5,7 +5,7 @@ import type { Role } from './scope-service.js';
|
|
|
5
5
|
*
|
|
6
6
|
* Shared rather than left to each implementation because the rule is a
|
|
7
7
|
* contract, not a policy: a store that lets the console delete `buyer` makes
|
|
8
|
-
* every
|
|
8
|
+
* every virtual user and scenario written against `buyer` silently stop testing
|
|
9
9
|
* what it claims to, and nothing fails at the point of the mistake. Two
|
|
10
10
|
* implementations disagreeing about that would be worse than either rule.
|
|
11
11
|
*
|