@pikku/core 0.12.107 → 0.12.111
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 +344 -0
- package/dist/analytics/analytics.d.ts +6 -0
- package/dist/analytics/analytics.js +58 -0
- package/dist/analytics/analytics.types.d.ts +156 -0
- package/dist/analytics/analytics.types.js +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +23 -0
- package/dist/analytics/anonymous-analytics-identity.js +27 -0
- package/dist/analytics/compose-analytics-identity.d.ts +14 -0
- package/dist/analytics/compose-analytics-identity.js +33 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +24 -0
- package/dist/analytics/cookie-analytics-identity.js +37 -0
- package/dist/analytics/define-analytics-events.d.ts +22 -0
- package/dist/analytics/define-analytics-events.js +9 -0
- package/dist/analytics/fan-out-analytics.d.ts +15 -0
- package/dist/analytics/fan-out-analytics.js +36 -0
- package/dist/analytics/index.d.ts +13 -0
- package/dist/analytics/index.js +8 -0
- package/dist/analytics/logger-analytics-service.d.ts +14 -0
- package/dist/analytics/logger-analytics-service.js +23 -0
- package/dist/analytics/mint-cookie.d.ts +44 -0
- package/dist/analytics/mint-cookie.js +55 -0
- package/dist/errors/errors.d.ts +7 -0
- package/dist/errors/errors.js +17 -0
- package/dist/function/function-meta.types.d.ts +2 -0
- package/dist/function/function-runner.js +29 -0
- package/dist/function/functions.types.d.ts +22 -3
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/pikku-state.d.ts +1 -1
- package/dist/scopes.d.ts +11 -0
- package/dist/scopes.js +17 -0
- package/dist/services/credential-wire-service.d.ts +1 -1
- package/dist/services/feature-flag-service.d.ts +100 -0
- package/dist/services/feature-flag-service.js +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/meta-service.d.ts +16 -0
- package/dist/services/meta-service.js +19 -0
- package/dist/services/webhook-service.d.ts +7 -2
- package/dist/services/webhook-service.js +11 -6
- package/dist/testing/service-tests/agent-run-service-tests.d.ts +2 -2
- package/dist/testing/service-tests/agent-storage-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/channel-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/credential-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/deployment-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/event-hub-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/secret-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/session-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-run-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-service-tests.d.ts +1 -1
- package/dist/types/core.types.d.ts +23 -0
- package/dist/wirings/agent/agent-rpc.d.ts +1 -1
- package/dist/wirings/agent/agent-turn.d.ts +1 -1
- package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +1 -1
- package/dist/wirings/channel/channel-common.d.ts +1 -1
- package/dist/wirings/channel/channel-rpc-validators.d.ts +2 -2
- package/dist/wirings/channel/channel-runner.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
- package/dist/wirings/cli/channel/cli-approval.d.ts +2 -2
- package/dist/wirings/flag/assert-feature-available.d.ts +15 -0
- package/dist/wirings/flag/assert-feature-available.js +23 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +73 -0
- package/dist/wirings/flag/cached-flag-source.js +96 -0
- package/dist/wirings/flag/define-feature-flags.d.ts +33 -0
- package/dist/wirings/flag/define-feature-flags.js +32 -0
- package/dist/wirings/flag/flag.types.d.ts +97 -0
- package/dist/wirings/flag/flag.types.js +1 -0
- package/dist/wirings/flag/index.d.ts +7 -0
- package/dist/wirings/flag/index.js +5 -0
- package/dist/wirings/flag/resolve-flag.d.ts +52 -0
- package/dist/wirings/flag/resolve-flag.js +90 -0
- package/dist/wirings/flag/validate-flag-definitions.d.ts +26 -0
- package/dist/wirings/flag/validate-flag-definitions.js +103 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +8 -8
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +1 -1
- package/dist/wirings/workflow/workflow-queue-routing.d.ts +1 -1
- package/package.json +11 -5
- package/run-tests.sh +17 -9
- package/src/public-surface.json +26 -0
- package/src/agent-naming.test.ts +0 -68
- package/src/api-report.test.ts +0 -138
- package/src/app-alias-surface.test.ts +0 -179
- package/src/app-leaf-surface.test.ts +0 -222
- package/src/bootstrap-compat/root.ts +0 -20
- package/src/classification/column-form.test.ts +0 -97
- package/src/classification/column-form.ts +0 -55
- package/src/classification/data-classification.ts +0 -73
- package/src/classification/index.ts +0 -40
- package/src/classification/key-ids.ts +0 -2
- package/src/classification/secret-value.test.ts +0 -204
- package/src/classification/secret-value.ts +0 -106
- package/src/crypto-utils.test.ts +0 -668
- package/src/crypto-utils.ts +0 -460
- package/src/dev/hot-reload.test.ts +0 -587
- package/src/dev/hot-reload.ts +0 -225
- package/src/dev/module-runner.test.ts +0 -235
- package/src/dev/module-runner.ts +0 -138
- package/src/dev/reload-meta.test.ts +0 -183
- package/src/dev/reload-meta.ts +0 -144
- package/src/ecosystem-tier-removed.test.ts +0 -72
- package/src/env.ts +0 -1
- package/src/errors/error-handler.ts +0 -77
- package/src/errors/error.test.ts +0 -229
- package/src/errors/errors.ts +0 -393
- package/src/errors/index.ts +0 -11
- package/src/errors/serialized-error.ts +0 -12
- package/src/factory-functions.test.ts +0 -111
- package/src/function/abort-scope.test.ts +0 -97
- package/src/function/abort-scope.ts +0 -80
- package/src/function/function-meta.types.ts +0 -151
- package/src/function/function-runner.test.ts +0 -1619
- package/src/function/function-runner.ts +0 -499
- package/src/function/functions.types.ts +0 -319
- package/src/function/index.ts +0 -40
- package/src/function/list.types.test.ts +0 -100
- package/src/function/list.types.ts +0 -69
- package/src/function/pikku-request.test.ts +0 -35
- package/src/function/pikku-request.ts +0 -17
- package/src/gopass-secrets-removed.test.ts +0 -51
- package/src/handle-error.test.ts +0 -532
- package/src/handle-error.ts +0 -64
- package/src/middleware/auth-apikey.test.ts +0 -362
- package/src/middleware/auth-apikey.ts +0 -39
- package/src/middleware/auth-bearer.test.ts +0 -566
- package/src/middleware/auth-bearer.ts +0 -83
- package/src/middleware/auth-cookie.test.ts +0 -572
- package/src/middleware/auth-cookie.ts +0 -107
- package/src/middleware/cors.test.ts +0 -579
- package/src/middleware/cors.ts +0 -103
- package/src/middleware/index.ts +0 -30
- package/src/middleware/middleware-factories.ts +0 -76
- package/src/middleware/middleware.types.ts +0 -61
- package/src/middleware/remote-auth.test.ts +0 -547
- package/src/middleware/remote-auth.ts +0 -95
- package/src/middleware/remote-jobs-secret.ts +0 -35
- package/src/middleware/require-origin.test.ts +0 -115
- package/src/middleware/require-origin.ts +0 -79
- package/src/middleware/telemetry.ts +0 -83
- package/src/middleware-runner.test.ts +0 -578
- package/src/middleware-runner.ts +0 -232
- package/src/no-any-casts.test.ts +0 -57
- package/src/no-root-barrel.test.ts +0 -122
- package/src/permissions.test.ts +0 -256
- package/src/permissions.ts +0 -217
- package/src/pikku-state.test.ts +0 -198
- package/src/pikku-state.ts +0 -206
- package/src/production-barrels-stay-lean.test.ts +0 -110
- package/src/public-surface.test.ts +0 -133
- package/src/remote.test.ts +0 -173
- package/src/remote.ts +0 -56
- package/src/removed-legacy-exports.test.ts +0 -66
- package/src/run-tests-script.test.ts +0 -67
- package/src/schema.test.ts +0 -430
- package/src/schema.ts +0 -204
- package/src/scopes.test.ts +0 -203
- package/src/scopes.ts +0 -67
- package/src/services/agent-run-state-service.ts +0 -37
- package/src/services/agent-runner-service.ts +0 -238
- package/src/services/agent-storage-service.ts +0 -39
- package/src/services/ai-embedding-service.ts +0 -9
- package/src/services/audit-service.test.ts +0 -44
- package/src/services/audit-service.ts +0 -280
- package/src/services/content-service.ts +0 -65
- package/src/services/credential-service.ts +0 -20
- package/src/services/credential-wire-service.test.ts +0 -235
- package/src/services/credential-wire-service.ts +0 -120
- package/src/services/deployment-service.ts +0 -32
- package/src/services/email-service.test.ts +0 -100
- package/src/services/email-service.ts +0 -60
- package/src/services/email-template.test.ts +0 -311
- package/src/services/email-template.ts +0 -254
- package/src/services/file-scenario-run-store.test.ts +0 -349
- package/src/services/file-scenario-run-store.ts +0 -282
- package/src/services/gateway-service.ts +0 -5
- package/src/services/http-personas-converse.test.ts +0 -274
- package/src/services/http-personas.test.ts +0 -379
- package/src/services/http-personas.ts +0 -508
- package/src/services/in-memory-agent-run-state-service.ts +0 -87
- package/src/services/in-memory-queue-service.test.ts +0 -162
- package/src/services/in-memory-queue-service.ts +0 -78
- package/src/services/in-memory-session-store.test.ts +0 -58
- package/src/services/in-memory-session-store.ts +0 -20
- package/src/services/in-memory-trigger-service.ts +0 -47
- package/src/services/in-memory-workflow-service.test.ts +0 -430
- package/src/services/in-memory-workflow-service.ts +0 -595
- package/src/services/index.ts +0 -192
- package/src/services/istanbul-coverage-service.test.ts +0 -66
- package/src/services/istanbul-coverage-service.ts +0 -59
- package/src/services/jwt-service.ts +0 -15
- package/src/services/local-content-request-handler.test.ts +0 -240
- package/src/services/local-content-request-handler.ts +0 -295
- package/src/services/local-content.test.ts +0 -186
- package/src/services/local-content.ts +0 -242
- package/src/services/local-credential-service.ts +0 -63
- package/src/services/local-email-service.test.ts +0 -182
- package/src/services/local-email-service.ts +0 -43
- package/src/services/local-gateway-service.ts +0 -51
- package/src/services/local-secrets.test.ts +0 -95
- package/src/services/local-secrets.ts +0 -71
- package/src/services/local-variables.test.ts +0 -61
- package/src/services/local-variables.ts +0 -45
- package/src/services/logger-console.test.ts +0 -117
- package/src/services/logger-console.ts +0 -174
- package/src/services/logger.ts +0 -48
- package/src/services/meta-service.test.ts +0 -75
- package/src/services/meta-service.ts +0 -767
- package/src/services/persona-actor-secret.test.ts +0 -68
- package/src/services/persona-actor-secret.ts +0 -70
- package/src/services/persona-sign-in.test.ts +0 -219
- package/src/services/persona-sign-in.ts +0 -238
- package/src/services/personas-service.ts +0 -191
- package/src/services/pikku-user-id.test.ts +0 -62
- package/src/services/pikku-user-id.ts +0 -13
- package/src/services/queue-webhook-service.test.ts +0 -409
- package/src/services/queue-webhook-service.ts +0 -150
- package/src/services/remote-jobs.test.ts +0 -106
- package/src/services/remote-jobs.ts +0 -92
- package/src/services/scheduler-service.ts +0 -37
- package/src/services/schema-service.ts +0 -10
- package/src/services/scope-service.ts +0 -91
- package/src/services/scoped-credential-service.test.ts +0 -86
- package/src/services/scoped-credential-service.ts +0 -63
- package/src/services/scoped-secret-service.test.ts +0 -93
- package/src/services/scoped-secret-service.ts +0 -40
- package/src/services/secret-host-binding.test.ts +0 -138
- package/src/services/secret-host-binding.ts +0 -51
- package/src/services/secret-service.ts +0 -25
- package/src/services/secretless.test.ts +0 -54
- package/src/services/secretless.ts +0 -29
- package/src/services/session-store.ts +0 -9
- package/src/services/stub-tracker.test.ts +0 -104
- package/src/services/stub-tracker.ts +0 -175
- package/src/services/system-role-guard.test.ts +0 -96
- package/src/services/system-role-guard.ts +0 -71
- package/src/services/temporary-file-service.ts +0 -76
- package/src/services/trigger-service.ts +0 -5
- package/src/services/typed-credential-service.ts +0 -83
- package/src/services/typed-secret-service.test.ts +0 -204
- package/src/services/typed-secret-service.ts +0 -132
- package/src/services/typed-variables-service.test.ts +0 -166
- package/src/services/typed-variables-service.ts +0 -166
- package/src/services/user-session-service.test.ts +0 -147
- package/src/services/user-session-service.ts +0 -85
- package/src/services/v8-coverage-service.test.ts +0 -69
- package/src/services/v8-coverage-service.ts +0 -163
- package/src/services/variables-service.ts +0 -13
- package/src/services/webhook-service.ts +0 -147
- package/src/services/workflow-service.ts +0 -120
- package/src/side-effects-are-declared.test.ts +0 -84
- package/src/source-files-stay-composable.test.ts +0 -41
- package/src/template-alias-surface.test.ts +0 -240
- package/src/test-utils.ts +0 -38
- package/src/testing/index.ts +0 -3
- package/src/testing/service-tests/agent-run-service-tests.ts +0 -98
- package/src/testing/service-tests/agent-storage-service-tests.ts +0 -379
- package/src/testing/service-tests/channel-store-tests.ts +0 -98
- package/src/testing/service-tests/credential-service-tests.ts +0 -143
- package/src/testing/service-tests/deployment-service-tests.ts +0 -33
- package/src/testing/service-tests/event-hub-store-tests.ts +0 -48
- package/src/testing/service-tests/secret-service-tests.ts +0 -105
- package/src/testing/service-tests/session-store-tests.ts +0 -62
- package/src/testing/service-tests/workflow-run-service-tests.ts +0 -59
- package/src/testing/service-tests/workflow-service-tests.ts +0 -308
- package/src/testing/service-tests.ts +0 -95
- package/src/time-utils.test.ts +0 -56
- package/src/time-utils.ts +0 -89
- package/src/types/core.types.ts +0 -446
- package/src/types/index.ts +0 -25
- package/src/types/state.types.ts +0 -226
- package/src/types/typed-credentials.test.ts +0 -72
- package/src/utils/hash.test.ts +0 -68
- package/src/utils/hash.ts +0 -26
- package/src/utils/hmac.ts +0 -21
- package/src/utils/node-host-resolver.ts +0 -20
- package/src/utils/safe-fetch.test.ts +0 -515
- package/src/utils/safe-fetch.ts +0 -347
- package/src/utils.test.ts +0 -359
- package/src/utils.ts +0 -165
- package/src/version.test.ts +0 -80
- package/src/version.ts +0 -25
- package/src/wirings/actor-flow/actor-flow.types.ts +0 -40
- package/src/wirings/actor-flow/index.ts +0 -10
- package/src/wirings/actor-flow/run-conversation.test.ts +0 -187
- package/src/wirings/actor-flow/run-conversation.ts +0 -280
- package/src/wirings/addon/addon-auth-tags.test.ts +0 -219
- package/src/wirings/addon/addon-runner.ts +0 -236
- package/src/wirings/addon/addon-scopes.test.ts +0 -225
- package/src/wirings/addon/addon-secrets.test.ts +0 -391
- package/src/wirings/addon/index.ts +0 -12
- package/src/wirings/addon/remote-addon-auth.ts +0 -65
- package/src/wirings/addon/wire-addon.test.ts +0 -102
- package/src/wirings/addon/wire-addon.ts +0 -202
- package/src/wirings/addon/wire-remote-addon.ts +0 -41
- package/src/wirings/agent/agent-agui.test.ts +0 -1213
- package/src/wirings/agent/agent-agui.ts +0 -405
- package/src/wirings/agent/agent-authorization.test.ts +0 -208
- package/src/wirings/agent/agent-finalize.test.ts +0 -187
- package/src/wirings/agent/agent-finalize.ts +0 -197
- package/src/wirings/agent/agent-helpers.test.ts +0 -215
- package/src/wirings/agent/agent-helpers.ts +0 -96
- package/src/wirings/agent/agent-interrupt.test.ts +0 -833
- package/src/wirings/agent/agent-interrupt.ts +0 -400
- package/src/wirings/agent/agent-memory.test.ts +0 -397
- package/src/wirings/agent/agent-memory.ts +0 -496
- package/src/wirings/agent/agent-middleware.types.test.ts +0 -41
- package/src/wirings/agent/agent-model-config.test.ts +0 -103
- package/src/wirings/agent/agent-model-config.ts +0 -59
- package/src/wirings/agent/agent-prepare.test.ts +0 -977
- package/src/wirings/agent/agent-prepare.ts +0 -1083
- package/src/wirings/agent/agent-registry.test.ts +0 -455
- package/src/wirings/agent/agent-registry.ts +0 -99
- package/src/wirings/agent/agent-resume-authorization.test.ts +0 -206
- package/src/wirings/agent/agent-rpc.ts +0 -116
- package/src/wirings/agent/agent-runner.test.ts +0 -1229
- package/src/wirings/agent/agent-runner.ts +0 -858
- package/src/wirings/agent/agent-stream-delegate.test.ts +0 -381
- package/src/wirings/agent/agent-stream-output-hooks.test.ts +0 -353
- package/src/wirings/agent/agent-stream.test.ts +0 -1800
- package/src/wirings/agent/agent-stream.ts +0 -1639
- package/src/wirings/agent/agent-thread-ownership.test.ts +0 -297
- package/src/wirings/agent/agent-turn.test.ts +0 -65
- package/src/wirings/agent/agent-turn.ts +0 -122
- package/src/wirings/agent/agent-utils.ts +0 -20
- package/src/wirings/agent/agent.types.ts +0 -676
- package/src/wirings/agent/index.ts +0 -58
- package/src/wirings/agent/voice-input.test.ts +0 -220
- package/src/wirings/agent/voice-input.ts +0 -180
- package/src/wirings/agent/voice-output.test.ts +0 -510
- package/src/wirings/agent/voice-output.ts +0 -311
- package/src/wirings/agent-scorer/agent-scorer-grade.test.ts +0 -106
- package/src/wirings/agent-scorer/agent-scorer-grade.ts +0 -55
- package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +0 -285
- package/src/wirings/agent-scorer/agent-scorer-judge.ts +0 -180
- package/src/wirings/agent-scorer/agent-scorer-live.test.ts +0 -174
- package/src/wirings/agent-scorer/agent-scorer-live.ts +0 -56
- package/src/wirings/agent-scorer/agent-scorer-registry.ts +0 -66
- package/src/wirings/agent-scorer/agent-scorer-sampling.test.ts +0 -34
- package/src/wirings/agent-scorer/agent-scorer-sampling.ts +0 -36
- package/src/wirings/agent-scorer/agent-scorer-snapshots.test.ts +0 -49
- package/src/wirings/agent-scorer/agent-scorer-snapshots.ts +0 -46
- package/src/wirings/agent-scorer/agent-scorer-worker.test.ts +0 -122
- package/src/wirings/agent-scorer/agent-scorer-worker.ts +0 -71
- package/src/wirings/agent-scorer/agent-scorer.ts +0 -102
- package/src/wirings/agent-scorer/agent-scorer.types.ts +0 -128
- package/src/wirings/agent-scorer/index.ts +0 -23
- package/src/wirings/channel/channel-common.ts +0 -102
- package/src/wirings/channel/channel-handler-shapes.test.ts +0 -72
- package/src/wirings/channel/channel-handler.test.ts +0 -322
- package/src/wirings/channel/channel-handler.ts +0 -259
- package/src/wirings/channel/channel-host-rpc.test.ts +0 -150
- package/src/wirings/channel/channel-host-rpc.ts +0 -69
- package/src/wirings/channel/channel-middleware-runner.test.ts +0 -188
- package/src/wirings/channel/channel-middleware-runner.ts +0 -126
- package/src/wirings/channel/channel-rpc-registry.ts +0 -116
- package/src/wirings/channel/channel-rpc-responder.ts +0 -117
- package/src/wirings/channel/channel-rpc-service.ts +0 -132
- package/src/wirings/channel/channel-rpc-validators.ts +0 -65
- package/src/wirings/channel/channel-rpc.test.ts +0 -841
- package/src/wirings/channel/channel-rpc.ts +0 -5
- package/src/wirings/channel/channel-rpc.types.ts +0 -160
- package/src/wirings/channel/channel-runner.ts +0 -164
- package/src/wirings/channel/channel-store.ts +0 -35
- package/src/wirings/channel/channel.types.ts +0 -193
- package/src/wirings/channel/define-channel-routes.ts +0 -5
- package/src/wirings/channel/eventhub-service.ts +0 -16
- package/src/wirings/channel/eventhub-store.ts +0 -13
- package/src/wirings/channel/index.ts +0 -40
- package/src/wirings/channel/local/index.ts +0 -3
- package/src/wirings/channel/local/local-channel-handler.ts +0 -98
- package/src/wirings/channel/local/local-channel-runner.test.ts +0 -339
- package/src/wirings/channel/local/local-channel-runner.ts +0 -271
- package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -77
- package/src/wirings/channel/local/local-eventhub-service.ts +0 -69
- package/src/wirings/channel/log-channels.ts +0 -16
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -135
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -60
- package/src/wirings/channel/serverless/index.ts +0 -6
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -328
- package/src/wirings/cli/channel/cli-approval.test.ts +0 -177
- package/src/wirings/cli/channel/cli-approval.ts +0 -135
- package/src/wirings/cli/channel/cli-channel-runner.ts +0 -118
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +0 -192
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +0 -148
- package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +0 -480
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +0 -188
- package/src/wirings/cli/channel/index.ts +0 -6
- package/src/wirings/cli/cli-runner.test.ts +0 -969
- package/src/wirings/cli/cli-runner.ts +0 -538
- package/src/wirings/cli/cli.types.ts +0 -388
- package/src/wirings/cli/command-parser.test.ts +0 -1120
- package/src/wirings/cli/command-parser.ts +0 -713
- package/src/wirings/cli/define-cli-commands.ts +0 -13
- package/src/wirings/cli/format-cli-error.test.ts +0 -91
- package/src/wirings/cli/format-cli-error.ts +0 -96
- package/src/wirings/cli/index.ts +0 -19
- package/src/wirings/credential/credential.types.ts +0 -37
- package/src/wirings/credential/define-credential.ts +0 -49
- package/src/wirings/credential/index.ts +0 -7
- package/src/wirings/credential/validate-credential-definitions.ts +0 -63
- package/src/wirings/gateway/gateway-authorization.test.ts +0 -575
- package/src/wirings/gateway/gateway-channel-meta.test.ts +0 -44
- package/src/wirings/gateway/gateway-runner.test.ts +0 -581
- package/src/wirings/gateway/gateway-runner.ts +0 -411
- package/src/wirings/gateway/gateway.types.ts +0 -137
- package/src/wirings/gateway/index.ts +0 -15
- package/src/wirings/http/http-routes.test.ts +0 -318
- package/src/wirings/http/http-routes.ts +0 -111
- package/src/wirings/http/http-runner-addon-ref.test.ts +0 -238
- package/src/wirings/http/http-runner.test.ts +0 -503
- package/src/wirings/http/http-runner.ts +0 -462
- package/src/wirings/http/http.types.ts +0 -307
- package/src/wirings/http/index.ts +0 -27
- package/src/wirings/http/log-http-routes.ts +0 -18
- package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -318
- package/src/wirings/http/pikku-fetch-http-request.ts +0 -260
- package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -123
- package/src/wirings/http/pikku-fetch-http-response.ts +0 -149
- package/src/wirings/http/routers/http-router.ts +0 -13
- package/src/wirings/http/routers/path-to-regex.test.ts +0 -306
- package/src/wirings/http/routers/path-to-regex.ts +0 -115
- package/src/wirings/http/web-request.test.ts +0 -382
- package/src/wirings/http/web-request.ts +0 -162
- package/src/wirings/mcp/index.ts +0 -26
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -388
- package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
- package/src/wirings/mcp/mcp-runner.test.ts +0 -588
- package/src/wirings/mcp/mcp-runner.ts +0 -330
- package/src/wirings/mcp/mcp.types.ts +0 -199
- package/src/wirings/node/index.ts +0 -2
- package/src/wirings/node/node.types.ts +0 -23
- package/src/wirings/oauth2/index.ts +0 -1
- package/src/wirings/oauth2/oauth2.types.ts +0 -12
- package/src/wirings/persona/define-personas.ts +0 -33
- package/src/wirings/persona/index.ts +0 -75
- package/src/wirings/persona/persona-app-scopes.test.ts +0 -47
- package/src/wirings/persona/persona-app-scopes.ts +0 -74
- package/src/wirings/persona/persona-email.ts +0 -87
- package/src/wirings/persona/persona-environments.test.ts +0 -194
- package/src/wirings/persona/persona-environments.ts +0 -138
- package/src/wirings/persona/persona-mailbox.ts +0 -156
- package/src/wirings/persona/persona.test.ts +0 -230
- package/src/wirings/persona/persona.types.ts +0 -156
- package/src/wirings/persona/validate-personas.ts +0 -137
- package/src/wirings/queue/index.ts +0 -29
- package/src/wirings/queue/queue-identity.test.ts +0 -454
- package/src/wirings/queue/queue-identity.ts +0 -176
- package/src/wirings/queue/queue-runner.test.ts +0 -705
- package/src/wirings/queue/queue-runner.ts +0 -181
- package/src/wirings/queue/queue.types.ts +0 -161
- package/src/wirings/queue/register-queue-helper.ts +0 -46
- package/src/wirings/queue/signed-queue-service.ts +0 -60
- package/src/wirings/queue/validate-worker-config.test.ts +0 -108
- package/src/wirings/queue/validate-worker-config.ts +0 -90
- package/src/wirings/role/define-system-role.ts +0 -33
- package/src/wirings/role/index.ts +0 -13
- package/src/wirings/role/role.test.ts +0 -104
- package/src/wirings/role/role.types.ts +0 -47
- package/src/wirings/role/validate-role-definitions.ts +0 -93
- package/src/wirings/rpc/index.ts +0 -8
- package/src/wirings/rpc/rpc-runner.test.ts +0 -1130
- package/src/wirings/rpc/rpc-runner.ts +0 -569
- package/src/wirings/rpc/rpc-types.ts +0 -87
- package/src/wirings/scheduler/index.ts +0 -11
- package/src/wirings/scheduler/log-schedulers.ts +0 -16
- package/src/wirings/scheduler/scheduler-runner.test.ts +0 -835
- package/src/wirings/scheduler/scheduler-runner.ts +0 -138
- package/src/wirings/scheduler/scheduler.types.ts +0 -42
- package/src/wirings/scope/define-scope.ts +0 -33
- package/src/wirings/scope/index.ts +0 -15
- package/src/wirings/scope/scope.test.ts +0 -159
- package/src/wirings/scope/scope.types.ts +0 -42
- package/src/wirings/scope/validate-scope-definitions.ts +0 -107
- package/src/wirings/secret/index.ts +0 -9
- package/src/wirings/secret/secret.types.ts +0 -70
- package/src/wirings/secret/validate-secret-definitions.test.ts +0 -232
- package/src/wirings/secret/validate-secret-definitions.ts +0 -88
- package/src/wirings/trigger/index.ts +0 -9
- package/src/wirings/trigger/pikku-trigger-service.ts +0 -107
- package/src/wirings/trigger/trigger-runner.test.ts +0 -78
- package/src/wirings/trigger/trigger-runner.ts +0 -113
- package/src/wirings/trigger/trigger.types.ts +0 -100
- package/src/wirings/variable/index.ts +0 -8
- package/src/wirings/variable/validate-variable-definitions.test.ts +0 -115
- package/src/wirings/variable/validate-variable-definitions.ts +0 -71
- package/src/wirings/variable/variable.types.ts +0 -40
- package/src/wirings/virtual-user/index.ts +0 -107
- package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +0 -115
- package/src/wirings/virtual-user/prepare-virtual-user-run.ts +0 -95
- package/src/wirings/virtual-user/run-virtual-user.test.ts +0 -774
- package/src/wirings/virtual-user/run-virtual-user.ts +0 -684
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-agents.ts +0 -62
- package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +0 -215
- package/src/wirings/virtual-user/virtual-user-catalogue.ts +0 -184
- package/src/wirings/virtual-user/virtual-user-derive.test.ts +0 -426
- package/src/wirings/virtual-user/virtual-user-derive.ts +0 -161
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +0 -68
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +0 -210
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +0 -218
- package/src/wirings/virtual-user/virtual-user-intents.ts +0 -185
- package/src/wirings/virtual-user/virtual-user-rng.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-rng.ts +0 -50
- package/src/wirings/virtual-user/virtual-user-run-store.ts +0 -131
- package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +0 -854
- package/src/wirings/virtual-user/virtual-user-scaffold.ts +0 -664
- package/src/wirings/virtual-user/virtual-user-schedule-store.ts +0 -93
- package/src/wirings/virtual-user/virtual-user-schedule.test.ts +0 -280
- package/src/wirings/virtual-user/virtual-user-schedule.ts +0 -156
- package/src/wirings/virtual-user/virtual-user-target.ts +0 -47
- package/src/wirings/virtual-user/virtual-user.types.ts +0 -215
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -709
- package/src/wirings/workflow/dsl/workflow-runner.ts +0 -25
- package/src/wirings/workflow/feature.test.ts +0 -131
- package/src/wirings/workflow/feature.ts +0 -59
- package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +0 -569
- package/src/wirings/workflow/graph/graph-foreach.test.ts +0 -626
- package/src/wirings/workflow/graph/graph-node.ts +0 -115
- package/src/wirings/workflow/graph/graph-runner.test.ts +0 -1049
- package/src/wirings/workflow/graph/graph-runner.ts +0 -1376
- package/src/wirings/workflow/graph/graph-validation.test.ts +0 -27
- package/src/wirings/workflow/graph/graph-validation.ts +0 -41
- package/src/wirings/workflow/graph/template.test.ts +0 -49
- package/src/wirings/workflow/graph/template.ts +0 -42
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -39
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -75
- package/src/wirings/workflow/index.ts +0 -107
- package/src/wirings/workflow/pikku-scenario-service.ts +0 -1013
- package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -963
- package/src/wirings/workflow/pikku-workflow-service.ts +0 -1993
- package/src/wirings/workflow/run-timeline.test.ts +0 -199
- package/src/wirings/workflow/run-timeline.ts +0 -185
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -107
- package/src/wirings/workflow/scenario-cookie-jar.ts +0 -57
- package/src/wirings/workflow/scenario-expectations.test.ts +0 -238
- package/src/wirings/workflow/scenario-hooks.test.ts +0 -259
- package/src/wirings/workflow/scenario-poll.test.ts +0 -64
- package/src/wirings/workflow/scenario-poll.ts +0 -27
- package/src/wirings/workflow/scenario-prose.test.ts +0 -275
- package/src/wirings/workflow/scenario-prose.ts +0 -86
- package/src/wirings/workflow/scenario-run.types.ts +0 -193
- package/src/wirings/workflow/scenario-service.test.ts +0 -147
- package/src/wirings/workflow/scenario-step-guards.ts +0 -23
- package/src/wirings/workflow/scenario-step.test.ts +0 -800
- package/src/wirings/workflow/scenario-step.types.ts +0 -262
- package/src/wirings/workflow/scenario-surface.test.ts +0 -146
- package/src/wirings/workflow/scenario-surface.ts +0 -71
- package/src/wirings/workflow/scenario.types.ts +0 -63
- package/src/wirings/workflow/workflow-approval-audit.ts +0 -47
- package/src/wirings/workflow/workflow-approval-policy.test.ts +0 -594
- package/src/wirings/workflow/workflow-approval-policy.ts +0 -68
- package/src/wirings/workflow/workflow-approval.ts +0 -290
- package/src/wirings/workflow/workflow-child-run-session.test.ts +0 -168
- package/src/wirings/workflow/workflow-constants.ts +0 -66
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +0 -116
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -55
- package/src/wirings/workflow/workflow-dispatch-relay.test.ts +0 -128
- package/src/wirings/workflow/workflow-errors.ts +0 -132
- package/src/wirings/workflow/workflow-inline-authority.test.ts +0 -175
- package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -51
- package/src/wirings/workflow/workflow-invocation-id.ts +0 -28
- package/src/wirings/workflow/workflow-meta-resolver.ts +0 -45
- package/src/wirings/workflow/workflow-mirror.test.ts +0 -171
- package/src/wirings/workflow/workflow-missing-meta.test.ts +0 -92
- package/src/wirings/workflow/workflow-on-error.test.ts +0 -145
- package/src/wirings/workflow/workflow-queue-routing.ts +0 -129
- package/src/wirings/workflow/workflow-queue-wiring.ts +0 -149
- package/src/wirings/workflow/workflow-queue-workers.test.ts +0 -131
- package/src/wirings/workflow/workflow-queue-workers.ts +0 -66
- package/src/wirings/workflow/workflow-recovery.ts +0 -192
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +0 -140
- package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -113
- package/src/wirings/workflow/workflow-run-authority.test.ts +0 -212
- package/src/wirings/workflow/workflow-run-context.test.ts +0 -172
- package/src/wirings/workflow/workflow-run-engine.types.ts +0 -92
- package/src/wirings/workflow/workflow-run-ownership.ts +0 -37
- package/src/wirings/workflow/workflow-run-polling.test.ts +0 -127
- package/src/wirings/workflow/workflow-stalled-recovery.test.ts +0 -152
- package/src/wirings/workflow/workflow-status-stream.test.ts +0 -354
- package/src/wirings/workflow/workflow-status-stream.ts +0 -144
- package/src/wirings/workflow/workflow-step-claim.ts +0 -46
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +0 -94
- package/src/wirings/workflow/workflow-step-session.test.ts +0 -87
- package/src/wirings/workflow/workflow-suspend.ts +0 -61
- package/src/wirings/workflow/workflow-terminal-run-guard.test.ts +0 -105
- package/src/wirings/workflow/workflow.types.ts +0 -268
- package/src/wirings-stay-decoupled.test.ts +0 -130
- package/tsconfig.json +0 -14
- package/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.type-tests.json +0 -15
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import { describe, test } from 'node:test'
|
|
3
|
-
import { reachableAgents } from './virtual-user-agents.js'
|
|
4
|
-
|
|
5
|
-
const AGENTS = {
|
|
6
|
-
'router-agent': {
|
|
7
|
-
description: 'Routes requests to the right domain agent',
|
|
8
|
-
},
|
|
9
|
-
'social-poster': {
|
|
10
|
-
description: 'Drafts and schedules posts',
|
|
11
|
-
scopes: ['content:write'],
|
|
12
|
-
},
|
|
13
|
-
'refund-agent': {
|
|
14
|
-
scopes: ['billing:write'],
|
|
15
|
-
},
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe('reachableAgents', () => {
|
|
19
|
-
test('offers every agent when the persona holds no scopes to filter by', () => {
|
|
20
|
-
assert.deepEqual(
|
|
21
|
-
reachableAgents(AGENTS).map((a) => a.name),
|
|
22
|
-
['router-agent', 'social-poster', 'refund-agent']
|
|
23
|
-
)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test('an agent gating itself with scopes is offered only to a persona holding them', () => {
|
|
27
|
-
assert.deepEqual(
|
|
28
|
-
reachableAgents(AGENTS, ['content:write']).map((a) => a.name),
|
|
29
|
-
['router-agent', 'social-poster']
|
|
30
|
-
)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
// Undeclared is not denied. A function gating itself with no scopes is open
|
|
34
|
-
// to everybody, and an agent has to read the same way — inventing a denial
|
|
35
|
-
// here would hide precisely the surfaces that really are open.
|
|
36
|
-
test('an agent declaring no scopes stays open to everybody', () => {
|
|
37
|
-
assert.deepEqual(
|
|
38
|
-
reachableAgents(AGENTS, []).map((a) => a.name),
|
|
39
|
-
['router-agent']
|
|
40
|
-
)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('carries the description through, which is what the model chooses on', () => {
|
|
44
|
-
const [router] = reachableAgents(AGENTS, ['content:write'])
|
|
45
|
-
assert.equal(
|
|
46
|
-
router!.description,
|
|
47
|
-
'Routes requests to the right domain agent'
|
|
48
|
-
)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('omits description rather than passing undefined', () => {
|
|
52
|
-
const refund = reachableAgents(AGENTS, ['billing:write']).find(
|
|
53
|
-
(a) => a.name === 'refund-agent'
|
|
54
|
-
)
|
|
55
|
-
assert.deepEqual(refund, { name: 'refund-agent' })
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test('offers the registration key, not the display name the agent declares', () => {
|
|
59
|
-
assert.deepEqual(
|
|
60
|
-
reachableAgents({ adminAgent: { description: 'Runs the place' } }),
|
|
61
|
-
[{ name: 'adminAgent', description: 'Runs the place' }]
|
|
62
|
-
)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
test('an agent carrying nothing but a key is still offered under it', () => {
|
|
66
|
-
assert.deepEqual(reachableAgents({ orphan: {} }), [{ name: 'orphan' }])
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
test('a project with no agents offers none', () => {
|
|
70
|
-
assert.deepEqual(reachableAgents({}, ['admin']), [])
|
|
71
|
-
})
|
|
72
|
-
})
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { hasScopes } from '../../scopes.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Which of the product's agents a persona can actually talk to.
|
|
5
|
-
*
|
|
6
|
-
* An agent is not something a persona declares. It is something a persona
|
|
7
|
-
* *reaches*, under exactly the rule an RPC is reached by: `CoreAgent.scopes`
|
|
8
|
-
* is checked against the session, so a persona holding the scopes an agent
|
|
9
|
-
* requires finds it in front of them, and one that does not, does not.
|
|
10
|
-
*
|
|
11
|
-
* That is the whole reason a persona has no `agent:` field. Naming one would
|
|
12
|
-
* add no capability the roles do not already confer, and would narrow the
|
|
13
|
-
* persona to a single brain when the interesting behaviour is the choice
|
|
14
|
-
* between calling the API directly and handing the work to a specialist.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/** The part of an agent's meta this needs. */
|
|
18
|
-
export interface AgentReachability {
|
|
19
|
-
description?: string
|
|
20
|
-
scopes?: readonly string[]
|
|
21
|
-
auth?: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** One agent, as it is offered to a virtual user. */
|
|
25
|
-
export interface ReachableAgent {
|
|
26
|
-
name: string
|
|
27
|
-
description?: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The agents to offer, named by the key they are registered under.
|
|
32
|
-
*
|
|
33
|
-
* That key is the export's own name, which is what `addAgent` stores and what
|
|
34
|
-
* `resolveAgent` looks up. The `name` an agent declares in its config is a
|
|
35
|
-
* display label and is frequently something else entirely — offering that one
|
|
36
|
-
* hands the persona a name the server cannot resolve, and the run dies on a
|
|
37
|
-
* 500 the moment it takes the offer.
|
|
38
|
-
*
|
|
39
|
-
* Like {@link reachableCatalogue}, this narrows *what is offered* and never
|
|
40
|
-
* what is enforced: the server decides who may talk to what, and an agent
|
|
41
|
-
* answering a persona this filter would have withheld is a finding rather than
|
|
42
|
-
* a bug here.
|
|
43
|
-
*
|
|
44
|
-
* An agent declaring no scopes is offered to everybody, on the same terms as a
|
|
45
|
-
* function that gates itself with none — undeclared is not the same as denied,
|
|
46
|
-
* and inventing a denial here would hide the endpoints that really are open.
|
|
47
|
-
*/
|
|
48
|
-
export const reachableAgents = (
|
|
49
|
-
agents: Readonly<Record<string, AgentReachability>>,
|
|
50
|
-
scopes?: readonly string[]
|
|
51
|
-
): ReachableAgent[] =>
|
|
52
|
-
Object.entries(agents)
|
|
53
|
-
.filter(([, agent]) => {
|
|
54
|
-
if (!scopes || !agent.scopes?.length) {
|
|
55
|
-
return true
|
|
56
|
-
}
|
|
57
|
-
return hasScopes(agent.scopes, scopes)
|
|
58
|
-
})
|
|
59
|
-
.map(([id, agent]) => ({
|
|
60
|
-
name: id,
|
|
61
|
-
...(agent.description ? { description: agent.description } : {}),
|
|
62
|
-
}))
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { describe, test } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
catalogueClassification,
|
|
6
|
-
catalogueIndex,
|
|
7
|
-
catalogueLookup,
|
|
8
|
-
describeEntry,
|
|
9
|
-
isReadOnly,
|
|
10
|
-
reachableCatalogue,
|
|
11
|
-
unreachableCatalogue,
|
|
12
|
-
renderCatalogue,
|
|
13
|
-
} from './virtual-user-catalogue.js'
|
|
14
|
-
import type { ApiCatalogueEntry } from './virtual-user.types.js'
|
|
15
|
-
|
|
16
|
-
const entry = (
|
|
17
|
-
name: string,
|
|
18
|
-
extra: Partial<ApiCatalogueEntry> = {}
|
|
19
|
-
): ApiCatalogueEntry => ({ name, ...extra })
|
|
20
|
-
|
|
21
|
-
describe('read/write classification', () => {
|
|
22
|
-
test('an explicit annotation always wins over the name', () => {
|
|
23
|
-
assert.equal(isReadOnly(entry('getProject', { readonly: false })), false)
|
|
24
|
-
assert.equal(isReadOnly(entry('deleteProject', { readonly: true })), true)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test('without one, the name decides', () => {
|
|
28
|
-
for (const name of [
|
|
29
|
-
'getProject',
|
|
30
|
-
'listProjects',
|
|
31
|
-
'searchUsers',
|
|
32
|
-
'findOrg',
|
|
33
|
-
'countDeployments',
|
|
34
|
-
'isMember',
|
|
35
|
-
'hasAccess',
|
|
36
|
-
]) {
|
|
37
|
-
assert.equal(isReadOnly(entry(name)), true, name)
|
|
38
|
-
}
|
|
39
|
-
for (const name of [
|
|
40
|
-
'createProject',
|
|
41
|
-
'deployStage',
|
|
42
|
-
'inviteMember',
|
|
43
|
-
'rollbackDeployment',
|
|
44
|
-
'updateOrg',
|
|
45
|
-
]) {
|
|
46
|
-
assert.equal(isReadOnly(entry(name)), false, name)
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('a read prefix only counts on a word boundary', () => {
|
|
51
|
-
// 'checkoutCart' starts with 'check' but is emphatically not a read.
|
|
52
|
-
assert.equal(isReadOnly(entry('checkoutCart')), false)
|
|
53
|
-
assert.equal(isReadOnly(entry('issueRefund')), false)
|
|
54
|
-
assert.equal(isReadOnly(entry('countersignContract')), false)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
test('how much of the split is guess is reported rather than hidden', () => {
|
|
58
|
-
const classification = catalogueClassification([
|
|
59
|
-
entry('getProject', { readonly: true }),
|
|
60
|
-
entry('createProject', { readonly: false }),
|
|
61
|
-
entry('deployStage'),
|
|
62
|
-
entry('listStages'),
|
|
63
|
-
])
|
|
64
|
-
assert.deepEqual(classification, { total: 4, annotated: 2, inferred: 2 })
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
describe('catalogue rendering', () => {
|
|
69
|
-
test('an entry renders as name(inputs) -> outputs — description', () => {
|
|
70
|
-
const rendered = renderCatalogue([
|
|
71
|
-
entry('createProject', {
|
|
72
|
-
inputKeys: ['name', 'orgId'],
|
|
73
|
-
outputKeys: ['projectId'],
|
|
74
|
-
description: 'Create a project',
|
|
75
|
-
}),
|
|
76
|
-
])
|
|
77
|
-
assert.equal(
|
|
78
|
-
rendered,
|
|
79
|
-
'createProject(name,orgId) -> projectId — Create a project'
|
|
80
|
-
)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
test('missing meta degrades quietly instead of rendering undefined', () => {
|
|
84
|
-
assert.equal(renderCatalogue([entry('ping')]), 'ping()')
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
test('only the first line of a description is used', () => {
|
|
88
|
-
const rendered = renderCatalogue([
|
|
89
|
-
entry('getOrg', { description: 'Read an org.\nWith more detail below.' }),
|
|
90
|
-
])
|
|
91
|
-
assert.equal(rendered, 'getOrg() — Read an org.')
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test('every reachable endpoint is listed — nothing is ranked away', () => {
|
|
95
|
-
const entries = Array.from({ length: 50 }, (_, i) => entry(`getThing${i}`))
|
|
96
|
-
assert.equal(renderCatalogue(entries).split('\n').length, 50)
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe('what a given user is offered', () => {
|
|
101
|
-
const entries = [
|
|
102
|
-
entry('getProject'),
|
|
103
|
-
entry('createProject'),
|
|
104
|
-
entry('deployStage', { approvalRequired: true }),
|
|
105
|
-
entry('listOrgs', { scopes: ['platform:admin'] }),
|
|
106
|
-
entry('getOrgMembers', { scopes: ['org:read'] }),
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
test('approval-gated calls are withheld by default', () => {
|
|
110
|
-
const names = reachableCatalogue(entries).map((e) => e.name)
|
|
111
|
-
assert.ok(!names.includes('deployStage'))
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test('and offered when the run opts in', () => {
|
|
115
|
-
const names = reachableCatalogue(entries, {
|
|
116
|
-
allowApprovalRequired: true,
|
|
117
|
-
}).map((e) => e.name)
|
|
118
|
-
assert.ok(names.includes('deployStage'))
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
test('a read-only user is offered no mutations at all', () => {
|
|
122
|
-
const names = reachableCatalogue(entries, { readOnly: true }).map(
|
|
123
|
-
(e) => e.name
|
|
124
|
-
)
|
|
125
|
-
assert.deepEqual(names, ['getProject', 'listOrgs', 'getOrgMembers'])
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
test('a scope the persona does not hold is left out', () => {
|
|
129
|
-
const names = reachableCatalogue(entries, {
|
|
130
|
-
scopes: ['org:read'],
|
|
131
|
-
}).map((e) => e.name)
|
|
132
|
-
assert.deepEqual(names, ['getProject', 'createProject', 'getOrgMembers'])
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
// The adversarial oracle: what it is NOT entitled to reach, so a 2xx from one
|
|
136
|
-
// of these is the finding rather than a pass.
|
|
137
|
-
test('the same split, the other way round', () => {
|
|
138
|
-
const names = unreachableCatalogue(entries, ['org:read']).map((e) => e.name)
|
|
139
|
-
assert.deepEqual(names, ['listOrgs'])
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
// Every scope a persona holds means the whole surface is entitled, which is
|
|
143
|
-
// what an unscoped project looks like — and an empty oracle is the honest
|
|
144
|
-
// answer there, not a catalogue of everything.
|
|
145
|
-
test('an unscoped catalogue has nothing to withhold', () => {
|
|
146
|
-
assert.deepEqual(
|
|
147
|
-
unreachableCatalogue([entry('getProject')], ['anything']),
|
|
148
|
-
[]
|
|
149
|
-
)
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
test('omitting scopes keeps everything — narrowing is opt-in', () => {
|
|
153
|
-
assert.equal(
|
|
154
|
-
reachableCatalogue(entries, { allowApprovalRequired: true }).length,
|
|
155
|
-
5
|
|
156
|
-
)
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
describe('describing an endpoint before calling it', () => {
|
|
161
|
-
test('hands back the full input schema, not just the key names', () => {
|
|
162
|
-
const described = describeEntry(
|
|
163
|
-
entry('createProject', {
|
|
164
|
-
description: 'Create a project',
|
|
165
|
-
inputSchema: {
|
|
166
|
-
type: 'object',
|
|
167
|
-
properties: { name: { type: 'string' } },
|
|
168
|
-
required: ['name'],
|
|
169
|
-
},
|
|
170
|
-
outputSchema: { type: 'object', properties: { projectId: {} } },
|
|
171
|
-
})
|
|
172
|
-
)
|
|
173
|
-
assert.equal(described.name, 'createProject')
|
|
174
|
-
assert.equal(described.readonly, false)
|
|
175
|
-
assert.equal(described.approvalRequired, false)
|
|
176
|
-
assert.deepEqual(described.input, {
|
|
177
|
-
type: 'object',
|
|
178
|
-
properties: { name: { type: 'string' } },
|
|
179
|
-
required: ['name'],
|
|
180
|
-
})
|
|
181
|
-
assert.ok(described.output)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('an endpoint with no schema still describes as callable with nothing', () => {
|
|
185
|
-
const described = describeEntry(entry('ping'))
|
|
186
|
-
assert.deepEqual(described.input, { type: 'object', properties: {} })
|
|
187
|
-
assert.equal(described.output, null)
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
describe('catalogue index', () => {
|
|
192
|
-
test('looks endpoints up by name', () => {
|
|
193
|
-
const index = catalogueIndex([entry('getProject'), entry('createProject')])
|
|
194
|
-
assert.equal(index.get('getProject')?.name, 'getProject')
|
|
195
|
-
assert.equal(index.get('nonsense'), undefined)
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
// Found by running one: a model that has just read `whoAmI() -> userId,scopes`
|
|
199
|
-
// off the catalogue will sometimes hand the whole line back as the name.
|
|
200
|
-
test('an rpc name given with the signature the catalogue printed still resolves', () => {
|
|
201
|
-
const index = catalogueIndex([entry('getProject'), entry('createProject')])
|
|
202
|
-
assert.equal(catalogueLookup(index, 'getProject')?.name, 'getProject')
|
|
203
|
-
assert.equal(
|
|
204
|
-
catalogueLookup(index, 'getProject(id) -> project')?.name,
|
|
205
|
-
'getProject'
|
|
206
|
-
)
|
|
207
|
-
assert.equal(catalogueLookup(index, ' getProject() ')?.name, 'getProject')
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
test('a name that is genuinely not there is still not there', () => {
|
|
211
|
-
const index = catalogueIndex([entry('getProject'), entry('createProject')])
|
|
212
|
-
assert.equal(catalogueLookup(index, 'nope'), undefined)
|
|
213
|
-
assert.equal(catalogueLookup(index, 'nope(x) -> y'), undefined)
|
|
214
|
-
})
|
|
215
|
-
})
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import { hasScopes } from '../../scopes.js'
|
|
2
|
-
import type { ApiCatalogueEntry } from './virtual-user.types.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Endpoint names that only read, by convention. Used when nobody annotated
|
|
6
|
-
* `readonly` — which in a real project is most of them.
|
|
7
|
-
*/
|
|
8
|
-
const READ_PREFIXES = [
|
|
9
|
-
'get',
|
|
10
|
-
'list',
|
|
11
|
-
'lookup',
|
|
12
|
-
'search',
|
|
13
|
-
'find',
|
|
14
|
-
'read',
|
|
15
|
-
'fetch',
|
|
16
|
-
'check',
|
|
17
|
-
'count',
|
|
18
|
-
'query',
|
|
19
|
-
'preview',
|
|
20
|
-
'describe',
|
|
21
|
-
'has',
|
|
22
|
-
'is',
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Whether a call only reads.
|
|
27
|
-
*
|
|
28
|
-
* An explicit annotation always wins. Without one, the name decides — because
|
|
29
|
-
* an unannotated function means "nobody said", not "safe", and silently
|
|
30
|
-
* treating 395 unannotated endpoints as read-only is how a virtual user
|
|
31
|
-
* deploys something. {@link catalogueClassification} reports how much of the
|
|
32
|
-
* catalogue rests on this guess so the gap is visible rather than assumed.
|
|
33
|
-
*/
|
|
34
|
-
export const isReadOnly = (entry: ApiCatalogueEntry): boolean => {
|
|
35
|
-
if (typeof entry.readonly === 'boolean') return entry.readonly
|
|
36
|
-
const name = entry.name
|
|
37
|
-
return READ_PREFIXES.some(
|
|
38
|
-
(prefix) =>
|
|
39
|
-
name.startsWith(prefix) &&
|
|
40
|
-
(name.length === prefix.length ||
|
|
41
|
-
name[prefix.length] === name[prefix.length]?.toUpperCase())
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** How much of a catalogue's read/write split is annotation and how much is guess. */
|
|
46
|
-
export const catalogueClassification = (
|
|
47
|
-
entries: readonly ApiCatalogueEntry[]
|
|
48
|
-
) => {
|
|
49
|
-
const annotated = entries.filter(
|
|
50
|
-
(entry) => typeof entry.readonly === 'boolean'
|
|
51
|
-
).length
|
|
52
|
-
return {
|
|
53
|
-
total: entries.length,
|
|
54
|
-
annotated,
|
|
55
|
-
inferred: entries.length - annotated,
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** One catalogue line: `name(inputKeys) -> outputKeys — description`. */
|
|
60
|
-
const renderEntry = (entry: ApiCatalogueEntry): string => {
|
|
61
|
-
const inputs = (entry.inputKeys ?? []).join(',')
|
|
62
|
-
const outputs = (entry.outputKeys ?? []).join(',')
|
|
63
|
-
const description = entry.description
|
|
64
|
-
? ` — ${entry.description.split('\n')[0]!.slice(0, 120)}`
|
|
65
|
-
: ''
|
|
66
|
-
return `${entry.name}(${inputs})${outputs ? ` -> ${outputs}` : ''}${description}`
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* The whole reachable API as one compact index, for the instructions.
|
|
71
|
-
*
|
|
72
|
-
* Every endpoint is listed rather than retrieved against. Measured on a 430-RPC
|
|
73
|
-
* project this is ~8k tokens, cached for the life of the run — cheaper than any
|
|
74
|
-
* retrieval step, and it hides nothing. A ranking function would make the
|
|
75
|
-
* virtual user only as adventurous as the ranking, which loses exactly the
|
|
76
|
-
* endpoints worth stumbling into.
|
|
77
|
-
*/
|
|
78
|
-
export const renderCatalogue = (
|
|
79
|
-
entries: readonly ApiCatalogueEntry[]
|
|
80
|
-
): string => entries.map(renderEntry).join('\n')
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* The entries a given user may reach: approval-gated calls dropped unless the
|
|
84
|
-
* run opted in, mutations dropped for a read-only disposition, and anything the
|
|
85
|
-
* actor's tier cannot satisfy dropped when the caller supplied one.
|
|
86
|
-
*
|
|
87
|
-
* This narrows *what is offered*, never what is enforced — the server is the
|
|
88
|
-
* only thing that decides who may call what, and a call this filter would have
|
|
89
|
-
* denied still going through is a finding rather than a bug in the filter.
|
|
90
|
-
*/
|
|
91
|
-
export const reachableCatalogue = (
|
|
92
|
-
entries: readonly ApiCatalogueEntry[],
|
|
93
|
-
{
|
|
94
|
-
readOnly = false,
|
|
95
|
-
allowApprovalRequired = false,
|
|
96
|
-
scopes,
|
|
97
|
-
}: {
|
|
98
|
-
readOnly?: boolean
|
|
99
|
-
allowApprovalRequired?: boolean
|
|
100
|
-
/**
|
|
101
|
-
* The scopes this persona holds, resolved from its roles. Omit to keep
|
|
102
|
-
* every entry.
|
|
103
|
-
*
|
|
104
|
-
* Scopes rather than permission-function names: a function's `scopes` are
|
|
105
|
-
* declared and checkable, whereas a permission is arbitrary code whose
|
|
106
|
-
* verdict nobody can predict without running it. Narrowing by something
|
|
107
|
-
* unpredictable produced a catalogue that was wrong in both directions.
|
|
108
|
-
*/
|
|
109
|
-
scopes?: readonly string[]
|
|
110
|
-
} = {}
|
|
111
|
-
): ApiCatalogueEntry[] =>
|
|
112
|
-
entries.filter((entry) => {
|
|
113
|
-
if (entry.approvalRequired && !allowApprovalRequired) return false
|
|
114
|
-
if (readOnly && !isReadOnly(entry)) return false
|
|
115
|
-
if (scopes && entry.scopes?.length) {
|
|
116
|
-
return hasScopes(entry.scopes, scopes)
|
|
117
|
-
}
|
|
118
|
-
return true
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Endpoints this persona is *not* entitled to reach.
|
|
123
|
-
*
|
|
124
|
-
* The adversarial oracle. Withheld from the catalogue, so reaching one takes
|
|
125
|
-
* initiative — and a 2xx from one is the finding, because the server is the
|
|
126
|
-
* only thing that decides who may call what.
|
|
127
|
-
*/
|
|
128
|
-
export const unreachableCatalogue = (
|
|
129
|
-
entries: readonly ApiCatalogueEntry[],
|
|
130
|
-
scopes: readonly string[]
|
|
131
|
-
): ApiCatalogueEntry[] =>
|
|
132
|
-
entries.filter(
|
|
133
|
-
(entry) => !!entry.scopes?.length && !hasScopes(entry.scopes, scopes)
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
/** Index a catalogue by name for the engine's lookups. */
|
|
137
|
-
export const catalogueIndex = (
|
|
138
|
-
entries: readonly ApiCatalogueEntry[]
|
|
139
|
-
): Map<string, ApiCatalogueEntry> =>
|
|
140
|
-
new Map(entries.map((entry) => [entry.name, entry]))
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Find an entry by the name a model gave, forgiving the signature it just read.
|
|
144
|
-
*
|
|
145
|
-
* The catalogue renders as `name(inputs) -> outputs`, and a model that has the
|
|
146
|
-
* line in front of it will sometimes hand the whole line back — `whoAmI() ->
|
|
147
|
-
* userId,scopes` instead of `whoAmI`. Measured on a live run, 8 of 24 steps
|
|
148
|
-
* went that way and every one of them was answered with "there is no endpoint
|
|
149
|
-
* called that", which is true and useless.
|
|
150
|
-
*
|
|
151
|
-
* Forgiving it is not the same as guessing: an rpc name never contains a
|
|
152
|
-
* bracket, so everything from the first one is the signature the catalogue
|
|
153
|
-
* printed, and taking it off is unambiguous.
|
|
154
|
-
*/
|
|
155
|
-
export const catalogueLookup = (
|
|
156
|
-
index: Map<string, ApiCatalogueEntry>,
|
|
157
|
-
rpcName: string
|
|
158
|
-
): ApiCatalogueEntry | undefined => {
|
|
159
|
-
const exact = index.get(rpcName)
|
|
160
|
-
if (exact) {
|
|
161
|
-
return exact
|
|
162
|
-
}
|
|
163
|
-
const [head] = rpcName.trim().split('(')
|
|
164
|
-
return head && head !== rpcName ? index.get(head.trim()) : undefined
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* What `describe` hands back: the full schemas, so the next call can be made
|
|
169
|
-
* correctly rather than guessed at.
|
|
170
|
-
*
|
|
171
|
-
* Guessing field names is unproductive fuzz — every 400 becomes a typo and
|
|
172
|
-
* nothing is learned from any of them. Reading the schema first is also what a
|
|
173
|
-
* person does, since the form tells them the fields. It makes a subsequent 400
|
|
174
|
-
* mean something: either the schema and the implementation disagree, or the
|
|
175
|
-
* misuse is genuine and worth seeing.
|
|
176
|
-
*/
|
|
177
|
-
export const describeEntry = (entry: ApiCatalogueEntry) => ({
|
|
178
|
-
name: entry.name,
|
|
179
|
-
description: entry.description,
|
|
180
|
-
readonly: isReadOnly(entry),
|
|
181
|
-
approvalRequired: entry.approvalRequired ?? false,
|
|
182
|
-
input: entry.inputSchema ?? { type: 'object', properties: {} },
|
|
183
|
-
output: entry.outputSchema ?? null,
|
|
184
|
-
})
|