@kindgi/api 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-binding.d.ts +13 -0
- package/dist/agent-binding.d.ts.map +1 -1
- package/dist/agent-pins.d.ts.map +1 -1
- package/dist/agent-pins.js +18 -2
- package/dist/agent-pins.js.map +1 -1
- package/dist/app.d.ts +110 -17
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +163 -35
- package/dist/app.js.map +1 -1
- package/dist/block-publish.d.ts +56 -0
- package/dist/block-publish.d.ts.map +1 -0
- package/dist/block-publish.js +132 -0
- package/dist/block-publish.js.map +1 -0
- package/dist/caller.d.ts +24 -0
- package/dist/caller.d.ts.map +1 -0
- package/dist/caller.js +47 -0
- package/dist/caller.js.map +1 -0
- package/dist/capability-binding.d.ts +11 -0
- package/dist/capability-binding.d.ts.map +1 -1
- package/dist/cost-binding.d.ts +19 -0
- package/dist/cost-binding.d.ts.map +1 -1
- package/dist/cost-binding.js.map +1 -1
- package/dist/derive-agent-version.d.ts +7 -0
- package/dist/derive-agent-version.d.ts.map +1 -1
- package/dist/derive-agent-version.js +4 -0
- package/dist/derive-agent-version.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +75 -7
- package/dist/errors.js.map +1 -1
- package/dist/eval-case-binding.d.ts +16 -4
- package/dist/eval-case-binding.d.ts.map +1 -1
- package/dist/eval-run-binding.d.ts +31 -0
- package/dist/eval-run-binding.d.ts.map +1 -1
- package/dist/eval-run-dispatcher.d.ts +7 -0
- package/dist/eval-run-dispatcher.d.ts.map +1 -1
- package/dist/eval-run-dispatcher.js.map +1 -1
- package/dist/eval-sample.d.ts +11 -0
- package/dist/eval-sample.d.ts.map +1 -0
- package/dist/eval-sample.js +34 -0
- package/dist/eval-sample.js.map +1 -0
- package/dist/eval-suite-binding.d.ts +13 -0
- package/dist/eval-suite-binding.d.ts.map +1 -1
- package/dist/eval-suite-binding.js.map +1 -1
- package/dist/flow-binding.d.ts +18 -0
- package/dist/flow-binding.d.ts.map +1 -1
- package/dist/flow-pins.d.ts.map +1 -1
- package/dist/flow-pins.js +18 -2
- package/dist/flow-pins.js.map +1 -1
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +25 -0
- package/dist/gate.js.map +1 -1
- package/dist/handler-binding.d.ts +32 -0
- package/dist/handler-binding.d.ts.map +1 -1
- package/dist/hitl-binding.d.ts +23 -0
- package/dist/hitl-binding.d.ts.map +1 -1
- package/dist/identity-directory-binding.d.ts +82 -4
- package/dist/identity-directory-binding.d.ts.map +1 -1
- package/dist/identity-provider-binding.d.ts +197 -17
- package/dist/identity-provider-binding.d.ts.map +1 -1
- package/dist/improvement-pass-binding.d.ts +196 -0
- package/dist/improvement-pass-binding.d.ts.map +1 -0
- package/dist/improvement-pass-binding.js +9 -0
- package/dist/improvement-pass-binding.js.map +1 -0
- package/dist/index.d.ts +35 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/judged-dispatcher.d.ts +25 -4
- package/dist/judged-dispatcher.d.ts.map +1 -1
- package/dist/judged-dispatcher.js +43 -6
- package/dist/judged-dispatcher.js.map +1 -1
- package/dist/judgment-binding.d.ts +25 -1
- package/dist/judgment-binding.d.ts.map +1 -1
- package/dist/mcp-endpoint-binding.d.ts +7 -0
- package/dist/mcp-endpoint-binding.d.ts.map +1 -1
- package/dist/memory-binding.d.ts +124 -17
- package/dist/memory-binding.d.ts.map +1 -1
- package/dist/memory-erasure-binding.d.ts +145 -0
- package/dist/memory-erasure-binding.d.ts.map +1 -0
- package/dist/memory-erasure-binding.js +4 -0
- package/dist/memory-erasure-binding.js.map +1 -0
- package/dist/middleware/auth.d.ts +66 -13
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +150 -50
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/authorize.d.ts +9 -0
- package/dist/middleware/authorize.d.ts.map +1 -1
- package/dist/middleware/authorize.js +122 -4
- package/dist/middleware/authorize.js.map +1 -1
- package/dist/middleware/error-mapper.d.ts +5 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -1
- package/dist/middleware/error-mapper.js +14 -1
- package/dist/middleware/error-mapper.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +70 -5
- package/dist/middleware/idempotency.d.ts.map +1 -1
- package/dist/middleware/idempotency.js +174 -41
- package/dist/middleware/idempotency.js.map +1 -1
- package/dist/middleware/key-project.d.ts +17 -0
- package/dist/middleware/key-project.d.ts.map +1 -0
- package/dist/middleware/key-project.js +75 -0
- package/dist/middleware/key-project.js.map +1 -0
- package/dist/middleware/principal.d.ts.map +1 -1
- package/dist/middleware/principal.js +9 -5
- package/dist/middleware/principal.js.map +1 -1
- package/dist/middleware/project-ref.d.ts.map +1 -1
- package/dist/middleware/project-ref.js +3 -0
- package/dist/middleware/project-ref.js.map +1 -1
- package/dist/openapi/generate.d.ts.map +1 -1
- package/dist/openapi/generate.js +5 -2
- package/dist/openapi/generate.js.map +1 -1
- package/dist/openapi/operations.d.ts.map +1 -1
- package/dist/openapi/operations.js +919 -140
- package/dist/openapi/operations.js.map +1 -1
- package/dist/openapi/schemas.d.ts +90 -13
- package/dist/openapi/schemas.d.ts.map +1 -1
- package/dist/openapi/schemas.js +2081 -359
- package/dist/openapi/schemas.js.map +1 -1
- package/dist/person-grants-binding.d.ts +77 -0
- package/dist/person-grants-binding.d.ts.map +1 -0
- package/dist/person-grants-binding.js +4 -0
- package/dist/person-grants-binding.js.map +1 -0
- package/dist/proposal-service.d.ts +121 -0
- package/dist/proposal-service.d.ts.map +1 -0
- package/dist/proposal-service.js +447 -0
- package/dist/proposal-service.js.map +1 -0
- package/dist/proposal-status.d.ts +60 -0
- package/dist/proposal-status.d.ts.map +1 -0
- package/dist/proposal-status.js +109 -0
- package/dist/proposal-status.js.map +1 -0
- package/dist/provider-binding.d.ts +10 -0
- package/dist/provider-binding.d.ts.map +1 -1
- package/dist/publish-refused.d.ts +28 -3
- package/dist/publish-refused.d.ts.map +1 -1
- package/dist/publish-refused.js +24 -3
- package/dist/publish-refused.js.map +1 -1
- package/dist/routes/adapters.d.ts +2 -1
- package/dist/routes/adapters.d.ts.map +1 -1
- package/dist/routes/adapters.js +3 -1
- package/dist/routes/adapters.js.map +1 -1
- package/dist/routes/agent-releases.d.ts +55 -3
- package/dist/routes/agent-releases.d.ts.map +1 -1
- package/dist/routes/agent-releases.js +85 -55
- package/dist/routes/agent-releases.js.map +1 -1
- package/dist/routes/agents.d.ts +12 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +100 -2
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/approvals.d.ts +15 -3
- package/dist/routes/approvals.d.ts.map +1 -1
- package/dist/routes/approvals.js +133 -122
- package/dist/routes/approvals.js.map +1 -1
- package/dist/routes/artifacts.d.ts +25 -3
- package/dist/routes/artifacts.d.ts.map +1 -1
- package/dist/routes/artifacts.js +116 -7
- package/dist/routes/artifacts.js.map +1 -1
- package/dist/routes/auth.d.ts +25 -1
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +655 -281
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/blocks.d.ts.map +1 -1
- package/dist/routes/blocks.js +2 -42
- package/dist/routes/blocks.js.map +1 -1
- package/dist/routes/capabilities.d.ts +2 -1
- package/dist/routes/capabilities.d.ts.map +1 -1
- package/dist/routes/capabilities.js +6 -1
- package/dist/routes/capabilities.js.map +1 -1
- package/dist/routes/compliance.d.ts +9 -10
- package/dist/routes/compliance.d.ts.map +1 -1
- package/dist/routes/compliance.js +42 -61
- package/dist/routes/compliance.js.map +1 -1
- package/dist/routes/conversations.d.ts +8 -1
- package/dist/routes/conversations.d.ts.map +1 -1
- package/dist/routes/conversations.js +87 -8
- package/dist/routes/conversations.js.map +1 -1
- package/dist/routes/cost.d.ts +12 -1
- package/dist/routes/cost.d.ts.map +1 -1
- package/dist/routes/cost.js +74 -3
- package/dist/routes/cost.js.map +1 -1
- package/dist/routes/denied.d.ts +11 -0
- package/dist/routes/denied.d.ts.map +1 -0
- package/dist/routes/denied.js +17 -0
- package/dist/routes/denied.js.map +1 -0
- package/dist/routes/deployments.d.ts +10 -1
- package/dist/routes/deployments.d.ts.map +1 -1
- package/dist/routes/deployments.js +171 -13
- package/dist/routes/deployments.js.map +1 -1
- package/dist/routes/eval-comparison.d.ts.map +1 -1
- package/dist/routes/eval-comparison.js +69 -1
- package/dist/routes/eval-comparison.js.map +1 -1
- package/dist/routes/eval-overrides.d.ts +18 -0
- package/dist/routes/eval-overrides.d.ts.map +1 -0
- package/dist/routes/eval-overrides.js +81 -0
- package/dist/routes/eval-overrides.js.map +1 -0
- package/dist/routes/eval-runs.d.ts +10 -1
- package/dist/routes/eval-runs.d.ts.map +1 -1
- package/dist/routes/eval-runs.js +66 -7
- package/dist/routes/eval-runs.js.map +1 -1
- package/dist/routes/eval-suites.d.ts.map +1 -1
- package/dist/routes/eval-suites.js +28 -2
- package/dist/routes/eval-suites.js.map +1 -1
- package/dist/routes/event-triggers.d.ts +5 -1
- package/dist/routes/event-triggers.d.ts.map +1 -1
- package/dist/routes/event-triggers.js +26 -3
- package/dist/routes/event-triggers.js.map +1 -1
- package/dist/routes/export-signing-keys.d.ts +12 -0
- package/dist/routes/export-signing-keys.d.ts.map +1 -0
- package/dist/routes/export-signing-keys.js +24 -0
- package/dist/routes/export-signing-keys.js.map +1 -0
- package/dist/routes/flows.d.ts.map +1 -1
- package/dist/routes/flows.js +9 -1
- package/dist/routes/flows.js.map +1 -1
- package/dist/routes/gate-policies.d.ts +4 -1
- package/dist/routes/gate-policies.d.ts.map +1 -1
- package/dist/routes/gate-policies.js +29 -5
- package/dist/routes/gate-policies.js.map +1 -1
- package/dist/routes/guardrails.d.ts +16 -14
- package/dist/routes/guardrails.d.ts.map +1 -1
- package/dist/routes/guardrails.js +39 -3
- package/dist/routes/guardrails.js.map +1 -1
- package/dist/routes/identity.d.ts +20 -4
- package/dist/routes/identity.d.ts.map +1 -1
- package/dist/routes/identity.js +246 -6
- package/dist/routes/identity.js.map +1 -1
- package/dist/routes/improvement-passes.d.ts +52 -0
- package/dist/routes/improvement-passes.d.ts.map +1 -0
- package/dist/routes/improvement-passes.js +449 -0
- package/dist/routes/improvement-passes.js.map +1 -0
- package/dist/routes/judged-suites.d.ts +50 -0
- package/dist/routes/judged-suites.d.ts.map +1 -1
- package/dist/routes/judged-suites.js +66 -27
- package/dist/routes/judged-suites.js.map +1 -1
- package/dist/routes/judgment-context.d.ts +18 -2
- package/dist/routes/judgment-context.d.ts.map +1 -1
- package/dist/routes/judgment-context.js +63 -5
- package/dist/routes/judgment-context.js.map +1 -1
- package/dist/routes/judgment-flow-context.d.ts.map +1 -1
- package/dist/routes/judgment-flow-context.js +14 -2
- package/dist/routes/judgment-flow-context.js.map +1 -1
- package/dist/routes/judgments.d.ts.map +1 -1
- package/dist/routes/judgments.js +8 -1
- package/dist/routes/judgments.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +26 -1
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/memory-access.d.ts +43 -0
- package/dist/routes/memory-access.d.ts.map +1 -0
- package/dist/routes/memory-access.js +114 -0
- package/dist/routes/memory-access.js.map +1 -0
- package/dist/routes/memory-erasures.d.ts +25 -0
- package/dist/routes/memory-erasures.d.ts.map +1 -0
- package/dist/routes/memory-erasures.js +214 -0
- package/dist/routes/memory-erasures.js.map +1 -0
- package/dist/routes/memory-parse.d.ts +38 -0
- package/dist/routes/memory-parse.d.ts.map +1 -0
- package/dist/routes/memory-parse.js +199 -0
- package/dist/routes/memory-parse.js.map +1 -0
- package/dist/routes/memory.d.ts +9 -4
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/memory.js +226 -234
- package/dist/routes/memory.js.map +1 -1
- package/dist/routes/observations.d.ts +4 -1
- package/dist/routes/observations.d.ts.map +1 -1
- package/dist/routes/observations.js +8 -2
- package/dist/routes/observations.js.map +1 -1
- package/dist/routes/pagination.d.ts +7 -0
- package/dist/routes/pagination.d.ts.map +1 -1
- package/dist/routes/pagination.js +10 -0
- package/dist/routes/pagination.js.map +1 -1
- package/dist/routes/policies.d.ts +2 -1
- package/dist/routes/policies.d.ts.map +1 -1
- package/dist/routes/policies.js +3 -1
- package/dist/routes/policies.js.map +1 -1
- package/dist/routes/project-mismatch.d.ts +22 -0
- package/dist/routes/project-mismatch.d.ts.map +1 -0
- package/dist/routes/project-mismatch.js +34 -0
- package/dist/routes/project-mismatch.js.map +1 -0
- package/dist/routes/projects.d.ts +15 -4
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +100 -9
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/proposals.d.ts +25 -17
- package/dist/routes/proposals.d.ts.map +1 -1
- package/dist/routes/proposals.js +340 -507
- package/dist/routes/proposals.js.map +1 -1
- package/dist/routes/provenance.d.ts +17 -3
- package/dist/routes/provenance.d.ts.map +1 -1
- package/dist/routes/provenance.js +79 -103
- package/dist/routes/provenance.js.map +1 -1
- package/dist/routes/providers.d.ts +17 -1
- package/dist/routes/providers.d.ts.map +1 -1
- package/dist/routes/providers.js +110 -3
- package/dist/routes/providers.js.map +1 -1
- package/dist/routes/public-run-tokens.d.ts.map +1 -1
- package/dist/routes/public-run-tokens.js +3 -0
- package/dist/routes/public-run-tokens.js.map +1 -1
- package/dist/routes/readable-projects.d.ts +26 -0
- package/dist/routes/readable-projects.d.ts.map +1 -0
- package/dist/routes/readable-projects.js +39 -0
- package/dist/routes/readable-projects.js.map +1 -0
- package/dist/routes/runs.d.ts +10 -0
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/runs.js +92 -42
- package/dist/routes/runs.js.map +1 -1
- package/dist/routes/schedules.d.ts +21 -13
- package/dist/routes/schedules.d.ts.map +1 -1
- package/dist/routes/schedules.js +416 -55
- package/dist/routes/schedules.js.map +1 -1
- package/dist/routes/segments.d.ts +2 -0
- package/dist/routes/segments.d.ts.map +1 -1
- package/dist/routes/segments.js +5 -0
- package/dist/routes/segments.js.map +1 -1
- package/dist/routes/service-accounts.d.ts +17 -0
- package/dist/routes/service-accounts.d.ts.map +1 -0
- package/dist/routes/service-accounts.js +212 -0
- package/dist/routes/service-accounts.js.map +1 -0
- package/dist/routes/sign-in-options.d.ts +50 -0
- package/dist/routes/sign-in-options.d.ts.map +1 -0
- package/dist/routes/sign-in-options.js +98 -0
- package/dist/routes/sign-in-options.js.map +1 -0
- package/dist/routes/signing-keys.d.ts +2 -1
- package/dist/routes/signing-keys.d.ts.map +1 -1
- package/dist/routes/signing-keys.js +3 -1
- package/dist/routes/signing-keys.js.map +1 -1
- package/dist/routes/tenant-access.d.ts +13 -0
- package/dist/routes/tenant-access.d.ts.map +1 -0
- package/dist/routes/tenant-access.js +26 -0
- package/dist/routes/tenant-access.js.map +1 -0
- package/dist/routes/tenant.d.ts.map +1 -1
- package/dist/routes/tenant.js +4 -0
- package/dist/routes/tenant.js.map +1 -1
- package/dist/routes/token-sign-in.d.ts +36 -0
- package/dist/routes/token-sign-in.d.ts.map +1 -0
- package/dist/routes/token-sign-in.js +101 -0
- package/dist/routes/token-sign-in.js.map +1 -0
- package/dist/routes/tokens.d.ts +15 -5
- package/dist/routes/tokens.d.ts.map +1 -1
- package/dist/routes/tokens.js +162 -43
- package/dist/routes/tokens.js.map +1 -1
- package/dist/routes/tools.d.ts.map +1 -1
- package/dist/routes/tools.js +9 -1
- package/dist/routes/tools.js.map +1 -1
- package/dist/routes/trigger-access.d.ts +29 -0
- package/dist/routes/trigger-access.d.ts.map +1 -0
- package/dist/routes/trigger-access.js +33 -0
- package/dist/routes/trigger-access.js.map +1 -0
- package/dist/routes/webhook-endpoints.d.ts +2 -1
- package/dist/routes/webhook-endpoints.d.ts.map +1 -1
- package/dist/routes/webhook-endpoints.js +11 -3
- package/dist/routes/webhook-endpoints.js.map +1 -1
- package/dist/routes/webhooks.d.ts +5 -1
- package/dist/routes/webhooks.d.ts.map +1 -1
- package/dist/routes/webhooks.js +25 -2
- package/dist/routes/webhooks.js.map +1 -1
- package/dist/run-failure.d.ts +21 -0
- package/dist/run-failure.d.ts.map +1 -0
- package/dist/run-failure.js +29 -0
- package/dist/run-failure.js.map +1 -0
- package/dist/service-account-binding.d.ts +108 -0
- package/dist/service-account-binding.d.ts.map +1 -0
- package/dist/service-account-binding.js +4 -0
- package/dist/service-account-binding.js.map +1 -0
- package/dist/session-store-binding.d.ts +61 -13
- package/dist/session-store-binding.d.ts.map +1 -1
- package/dist/signed-export.d.ts +89 -0
- package/dist/signed-export.d.ts.map +1 -0
- package/dist/signed-export.js +149 -0
- package/dist/signed-export.js.map +1 -0
- package/dist/supervisor-binding.d.ts +186 -413
- package/dist/supervisor-binding.d.ts.map +1 -1
- package/dist/testing/app-bindings.d.ts +33 -0
- package/dist/testing/app-bindings.d.ts.map +1 -0
- package/dist/testing/app-bindings.js +112 -0
- package/dist/testing/app-bindings.js.map +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +13 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/stub-binding.d.ts +34 -0
- package/dist/testing/stub-binding.d.ts.map +1 -0
- package/dist/testing/stub-binding.js +42 -0
- package/dist/testing/stub-binding.js.map +1 -0
- package/dist/testing/trigger-registry.d.ts +21 -0
- package/dist/testing/trigger-registry.d.ts.map +1 -0
- package/dist/testing/trigger-registry.js +206 -0
- package/dist/testing/trigger-registry.js.map +1 -0
- package/dist/token-admin.d.ts +46 -8
- package/dist/token-admin.d.ts.map +1 -1
- package/dist/token-admin.js.map +1 -1
- package/dist/tool-binding.d.ts +13 -0
- package/dist/tool-binding.d.ts.map +1 -1
- package/dist/trigger-binding.d.ts +2 -2
- package/dist/trigger-binding.d.ts.map +1 -1
- package/dist/trigger-binding.js +1 -1
- package/dist/trigger-binding.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.d.ts +19 -3
- package/dist/webhook-endpoint-binding.d.ts.map +1 -1
- package/dist/webhook-endpoint-binding.js +1 -1
- package/dist/webhook-endpoint-binding.js.map +1 -1
- package/openapi.json +15387 -8789
- package/package.json +26 -22
- package/src/agent-binding.ts +14 -0
- package/src/agent-pins.ts +18 -2
- package/src/app.ts +366 -80
- package/src/block-publish.ts +181 -0
- package/src/caller.ts +62 -0
- package/src/capability-binding.ts +12 -0
- package/src/cost-binding.ts +19 -0
- package/src/derive-agent-version.ts +9 -1
- package/src/errors.ts +75 -7
- package/src/eval-case-binding.ts +17 -1
- package/src/eval-run-binding.ts +31 -0
- package/src/eval-run-dispatcher.ts +7 -0
- package/src/eval-sample.ts +42 -0
- package/src/eval-suite-binding.ts +14 -0
- package/src/flow-binding.ts +19 -0
- package/src/flow-pins.ts +18 -2
- package/src/gate.ts +26 -0
- package/src/handler-binding.ts +36 -1
- package/src/hitl-binding.ts +24 -0
- package/src/identity-directory-binding.ts +85 -4
- package/src/identity-provider-binding.ts +216 -21
- package/src/improvement-pass-binding.ts +193 -0
- package/src/index.ts +153 -31
- package/src/judged-dispatcher.ts +78 -11
- package/src/judgment-binding.ts +25 -1
- package/src/mcp-endpoint-binding.ts +7 -0
- package/src/memory-binding.ts +121 -17
- package/src/memory-erasure-binding.ts +156 -0
- package/src/middleware/auth.ts +228 -62
- package/src/middleware/authorize.ts +155 -3
- package/src/middleware/error-mapper.ts +15 -1
- package/src/middleware/idempotency.ts +230 -43
- package/src/middleware/key-project.ts +86 -0
- package/src/middleware/principal.ts +9 -5
- package/src/middleware/project-ref.ts +3 -0
- package/src/openapi/generate.ts +11 -2
- package/src/openapi/operations.ts +1060 -143
- package/src/openapi/schemas.ts +2387 -469
- package/src/person-grants-binding.ts +76 -0
- package/src/proposal-service.ts +640 -0
- package/src/proposal-status.ts +176 -0
- package/src/provider-binding.ts +10 -0
- package/src/publish-refused.ts +56 -9
- package/src/routes/adapters.ts +4 -0
- package/src/routes/agent-releases.ts +121 -69
- package/src/routes/agents.ts +128 -1
- package/src/routes/approvals.ts +164 -154
- package/src/routes/artifacts.ts +181 -11
- package/src/routes/auth.ts +804 -336
- package/src/routes/blocks.ts +2 -53
- package/src/routes/capabilities.ts +10 -1
- package/src/routes/compliance.ts +60 -99
- package/src/routes/conversations.ts +101 -7
- package/src/routes/cost.ts +110 -4
- package/src/routes/denied.ts +28 -0
- package/src/routes/deployments.ts +210 -17
- package/src/routes/eval-comparison.ts +81 -2
- package/src/routes/eval-overrides.ts +108 -0
- package/src/routes/eval-runs.ts +89 -6
- package/src/routes/eval-suites.ts +32 -2
- package/src/routes/event-triggers.ts +27 -3
- package/src/routes/export-signing-keys.ts +31 -0
- package/src/routes/flows.ts +12 -1
- package/src/routes/gate-policies.ts +37 -6
- package/src/routes/guardrails.ts +61 -2
- package/src/routes/identity.ts +328 -10
- package/src/routes/improvement-passes.ts +541 -0
- package/src/routes/judged-suites.ts +113 -43
- package/src/routes/judgment-context.ts +76 -5
- package/src/routes/judgment-flow-context.ts +16 -2
- package/src/routes/judgments.ts +17 -3
- package/src/routes/mcp.ts +29 -1
- package/src/routes/memory-access.ts +160 -0
- package/src/routes/memory-erasures.ts +240 -0
- package/src/routes/memory-parse.ts +250 -0
- package/src/routes/memory.ts +244 -286
- package/src/routes/observations.ts +15 -2
- package/src/routes/pagination.ts +12 -0
- package/src/routes/policies.ts +7 -1
- package/src/routes/project-mismatch.ts +56 -0
- package/src/routes/projects.ts +107 -13
- package/src/routes/proposals.ts +370 -611
- package/src/routes/provenance.ts +99 -133
- package/src/routes/providers.ts +142 -3
- package/src/routes/public-run-tokens.ts +3 -0
- package/src/routes/readable-projects.ts +66 -0
- package/src/routes/runs.ts +119 -39
- package/src/routes/schedules.ts +472 -60
- package/src/routes/segments.ts +11 -0
- package/src/routes/service-accounts.ts +262 -0
- package/src/routes/sign-in-options.ts +168 -0
- package/src/routes/signing-keys.ts +7 -1
- package/src/routes/tenant-access.ts +37 -0
- package/src/routes/tenant.ts +6 -0
- package/src/routes/token-sign-in.ts +161 -0
- package/src/routes/tokens.ts +172 -46
- package/src/routes/tools.ts +12 -1
- package/src/routes/trigger-access.ts +72 -0
- package/src/routes/webhook-endpoints.ts +15 -3
- package/src/routes/webhooks.ts +26 -2
- package/src/run-failure.ts +42 -0
- package/src/service-account-binding.ts +113 -0
- package/src/session-store-binding.ts +65 -13
- package/src/signed-export.ts +250 -0
- package/src/supervisor-binding.ts +169 -409
- package/src/testing/app-bindings.ts +142 -0
- package/src/testing/index.ts +21 -0
- package/src/testing/stub-binding.ts +53 -0
- package/src/testing/trigger-registry.ts +259 -0
- package/src/token-admin.ts +40 -8
- package/src/tool-binding.ts +14 -0
- package/src/trigger-binding.ts +8 -1
- package/src/types.ts +16 -0
- package/src/webhook-endpoint-binding.ts +18 -3
package/src/routes/agents.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
} from './agent-releases.js';
|
|
37
37
|
import { liveScopeToWire } from './live-scope-wire.js';
|
|
38
38
|
import { clampLimit } from './pagination.js';
|
|
39
|
+
import { projectMismatch } from './project-mismatch.js';
|
|
39
40
|
import { parseScopeParams } from './scope-params.js';
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -64,6 +65,8 @@ export function agentsRouter(
|
|
|
64
65
|
releases?: AgentReleaseBindings,
|
|
65
66
|
/** What a promotion's gate reads besides the releases (evals step 4b). */
|
|
66
67
|
gateDeps?: AgentReleaseGateDeps,
|
|
68
|
+
/** What the deployment can do for an agent's turns, for publish warnings. */
|
|
69
|
+
capabilities: AgentPublishCapabilities = {},
|
|
67
70
|
): Hono<AppEnv> {
|
|
68
71
|
const r = new Hono<AppEnv>();
|
|
69
72
|
// A read-only registry (under `kindgi dev`, the pack's files) refuses
|
|
@@ -170,8 +173,15 @@ export function agentsRouter(
|
|
|
170
173
|
...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
|
|
171
174
|
...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
|
|
172
175
|
});
|
|
176
|
+
// Only what the caller may read (T243 A), as `GET …/:id` asks.
|
|
177
|
+
const visible =
|
|
178
|
+
authorizer === undefined
|
|
179
|
+
? page.data
|
|
180
|
+
: await authorizer.filterByCan(c, 'read', page.data, (a) =>
|
|
181
|
+
ref('agent', a.id as unknown as string),
|
|
182
|
+
);
|
|
173
183
|
return c.json({
|
|
174
|
-
data:
|
|
184
|
+
data: visible.map(serializeAgent),
|
|
175
185
|
hasMore: page.nextCursor !== undefined,
|
|
176
186
|
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
177
187
|
});
|
|
@@ -383,6 +393,9 @@ export function agentsRouter(
|
|
|
383
393
|
if (outcome.kind === 'already-registered') {
|
|
384
394
|
return alreadyRegistered(c, binding, tenantId, outcome.agentId, outcome.version);
|
|
385
395
|
}
|
|
396
|
+
if (outcome.kind === 'project-mismatch') {
|
|
397
|
+
return projectMismatch(c, 'agent', outcome.agentId as unknown as string, outcome.projectId);
|
|
398
|
+
}
|
|
386
399
|
if (outcome.kind === 'project-not-found') {
|
|
387
400
|
// Caller supplied a `projectId` that does not resolve within
|
|
388
401
|
// this tenant. Distinct signal from `already-registered` so the
|
|
@@ -400,10 +413,12 @@ export function agentsRouter(
|
|
|
400
413
|
),
|
|
401
414
|
);
|
|
402
415
|
}
|
|
416
|
+
const warnings = publishWarnings(defined.value, capabilities);
|
|
403
417
|
c.status(201);
|
|
404
418
|
return c.json({
|
|
405
419
|
agentId: outcome.agentId as unknown as string,
|
|
406
420
|
version: outcome.version as unknown as string,
|
|
421
|
+
...(warnings.length > 0 && { warnings }),
|
|
407
422
|
});
|
|
408
423
|
});
|
|
409
424
|
|
|
@@ -668,9 +683,120 @@ function derived(
|
|
|
668
683
|
code: 'bad-input',
|
|
669
684
|
message: `\`projectId\` "${outcome.projectId as unknown as string}" does not resolve to a project in this tenant`,
|
|
670
685
|
});
|
|
686
|
+
case 'project-mismatch':
|
|
687
|
+
return projectMismatch(c, 'agent', agentId as unknown as string, outcome.projectId, 'derive');
|
|
671
688
|
}
|
|
672
689
|
}
|
|
673
690
|
|
|
691
|
+
/** What the deployment can do for an agent's turns, for publish warnings. */
|
|
692
|
+
export interface AgentPublishCapabilities {
|
|
693
|
+
/** Whether memory can search by meaning (embeddings are on). Absent: unknown, no warning. */
|
|
694
|
+
readonly semanticSearch?: boolean;
|
|
695
|
+
/** Whether agents can remember (`memory.remember`). Absent: unknown, no warning. */
|
|
696
|
+
readonly remember?: boolean;
|
|
697
|
+
/** Whether agent turns can recall earlier conversations. Absent: unknown, no warning. */
|
|
698
|
+
readonly conversationRecall?: boolean;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* What a published agent should know about this deployment before its
|
|
703
|
+
* first turn: an intent that searches by meaning on a runtime without
|
|
704
|
+
* embeddings fails its turns (`semantic`) or searches by keyword only
|
|
705
|
+
* (`both`); an agent that remembers on a runtime that can't store what
|
|
706
|
+
* it remembers gets "not remembered" from every call.
|
|
707
|
+
*/
|
|
708
|
+
function publishWarnings(
|
|
709
|
+
agent: Agent,
|
|
710
|
+
capabilities: AgentPublishCapabilities,
|
|
711
|
+
): { readonly code: string; readonly message: string }[] {
|
|
712
|
+
return [
|
|
713
|
+
...(capabilities.semanticSearch === false ? semanticWarnings(agent) : []),
|
|
714
|
+
...(capabilities.remember === false && agent.memory?.remember !== undefined
|
|
715
|
+
? [
|
|
716
|
+
{
|
|
717
|
+
code: 'remember-unavailable',
|
|
718
|
+
message:
|
|
719
|
+
'The agent declares memory.remember, and this runtime cannot store agent memories: each remember call answers that nothing was remembered.',
|
|
720
|
+
},
|
|
721
|
+
]
|
|
722
|
+
: []),
|
|
723
|
+
...recallWarnings(agent, capabilities),
|
|
724
|
+
];
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Intents over conversations: `same-segment` and `same-project` quote other
|
|
729
|
+
* people's conversations (always said); on a runtime that can't recall,
|
|
730
|
+
* every such intent recalls nothing.
|
|
731
|
+
*/
|
|
732
|
+
function recallWarnings(
|
|
733
|
+
agent: Agent,
|
|
734
|
+
capabilities: AgentPublishCapabilities,
|
|
735
|
+
): { readonly code: string; readonly message: string }[] {
|
|
736
|
+
const answers = agent.retrieval.findIndex(
|
|
737
|
+
(intent) => intent.source === 'conversations' && intent.roles?.includes('agent') === true,
|
|
738
|
+
);
|
|
739
|
+
const answersWarning =
|
|
740
|
+
answers >= 0 && capabilities.conversationRecall !== false
|
|
741
|
+
? [
|
|
742
|
+
{
|
|
743
|
+
code: 'recall-agent-answers',
|
|
744
|
+
message: `Retrieval intent ${answers} recalls the agent's own earlier answers: they can carry its earlier mistakes. They are quoted as "earlier answer by the agent, not verified"; recall only the people's own words (the default) to leave them out.`,
|
|
745
|
+
},
|
|
746
|
+
]
|
|
747
|
+
: [];
|
|
748
|
+
return [...answersWarning, ...perIntentRecallWarnings(agent, capabilities)];
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
function perIntentRecallWarnings(
|
|
752
|
+
agent: Agent,
|
|
753
|
+
capabilities: AgentPublishCapabilities,
|
|
754
|
+
): { readonly code: string; readonly message: string }[] {
|
|
755
|
+
return agent.retrieval.flatMap((intent, i) => {
|
|
756
|
+
if (intent.source !== 'conversations') return [];
|
|
757
|
+
if (capabilities.conversationRecall === false) {
|
|
758
|
+
return [
|
|
759
|
+
{
|
|
760
|
+
code: 'recall-unavailable',
|
|
761
|
+
message: `Retrieval intent ${i} recalls earlier conversations, and this runtime can't: it recalls nothing, and each turn's journal says so (no-recall).`,
|
|
762
|
+
},
|
|
763
|
+
];
|
|
764
|
+
}
|
|
765
|
+
if (intent.scope === 'same-segment' || intent.scope === 'same-project') {
|
|
766
|
+
const where = intent.scope === 'same-segment' ? "the run's segment" : "the run's project";
|
|
767
|
+
return [
|
|
768
|
+
{
|
|
769
|
+
code: 'recall-other-people',
|
|
770
|
+
message: `Retrieval intent ${i} recalls conversations in ${where}, whoever had them: this agent can quote other users' conversations in ${where}. Their messages are marked as another person's, without saying whose.`,
|
|
771
|
+
},
|
|
772
|
+
];
|
|
773
|
+
}
|
|
774
|
+
return [];
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function semanticWarnings(agent: Agent): { readonly code: string; readonly message: string }[] {
|
|
779
|
+
return agent.retrieval.flatMap((intent, i) => {
|
|
780
|
+
if (intent.mode === 'semantic') {
|
|
781
|
+
return [
|
|
782
|
+
{
|
|
783
|
+
code: 'semantic-unavailable',
|
|
784
|
+
message: `Retrieval intent ${i} searches by meaning (mode "semantic"), and this runtime has no embeddings: its turns fail with semantic-unavailable until an operator turns them on (KINDGI_MEMORY_EMBEDDINGS).`,
|
|
785
|
+
},
|
|
786
|
+
];
|
|
787
|
+
}
|
|
788
|
+
if (intent.mode === 'both') {
|
|
789
|
+
return [
|
|
790
|
+
{
|
|
791
|
+
code: 'semantic-unavailable',
|
|
792
|
+
message: `Retrieval intent ${i} (mode "both") runs only its keyword search: this runtime has no embeddings (KINDGI_MEMORY_EMBEDDINGS).`,
|
|
793
|
+
},
|
|
794
|
+
];
|
|
795
|
+
}
|
|
796
|
+
return [];
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
|
|
674
800
|
function serializeAgent(a: AgentVersionRecord): Record<string, unknown> {
|
|
675
801
|
return {
|
|
676
802
|
id: a.id as unknown as string,
|
|
@@ -684,6 +810,7 @@ function serializeAgent(a: AgentVersionRecord): Record<string, unknown> {
|
|
|
684
810
|
capabilities: a.capabilities,
|
|
685
811
|
tools: a.tools,
|
|
686
812
|
retrieval: a.retrieval,
|
|
813
|
+
...(a.memory !== undefined && { memory: a.memory }),
|
|
687
814
|
guardrails: a.guardrails,
|
|
688
815
|
...(a.conversationPolicy !== undefined && { conversationPolicy: a.conversationPolicy }),
|
|
689
816
|
...(a.budget !== undefined && { budget: a.budget }),
|
package/src/routes/approvals.ts
CHANGED
|
@@ -2,39 +2,48 @@
|
|
|
2
2
|
// Copyright (C) 2026 Kindgi Inc.
|
|
3
3
|
|
|
4
4
|
import { Hono } from 'hono';
|
|
5
|
+
import type { Context } from 'hono';
|
|
5
6
|
|
|
6
7
|
import { AGENT_GATE_SUBJECTS, TOOL_CALL_GATE_SUBJECT } from '@kindgi/agents';
|
|
7
8
|
import type { ConversationBinding, GateDecisionValue } from '@kindgi/agents';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
9
|
+
import type { AuditEventBinding } from '@kindgi/audit-events';
|
|
10
|
+
import { REVIEWER_ROLE_RANK, type ResourceRef, type ReviewerRole, ref } from '@kindgi/authz';
|
|
11
|
+
import type { ExportSigningBinding } from '@kindgi/crypto';
|
|
11
12
|
import type { RunBinding } from '@kindgi/runtime';
|
|
12
|
-
import { canonicalize } from '@kindgi/schema';
|
|
13
13
|
import type {
|
|
14
14
|
ApprovalId,
|
|
15
15
|
ConversationId,
|
|
16
16
|
Cursor,
|
|
17
17
|
ReviewerId,
|
|
18
18
|
RunId,
|
|
19
|
-
SigningKeyId,
|
|
20
19
|
TenantId,
|
|
21
20
|
Timestamp,
|
|
22
21
|
UserId,
|
|
23
22
|
} from '@kindgi/types';
|
|
24
23
|
|
|
25
24
|
import { statusFor, toWireError } from '../errors.js';
|
|
26
|
-
import type { RunHandlerBinding } from '../handler-binding.js';
|
|
25
|
+
import type { RunHandlerBinding, RunTrace } from '../handler-binding.js';
|
|
27
26
|
import type {
|
|
28
27
|
Approval,
|
|
28
|
+
ApprovalPosition,
|
|
29
29
|
ApprovalStatus,
|
|
30
30
|
HitlBinding,
|
|
31
31
|
ReviewDecisionKind,
|
|
32
32
|
ReviewDecisionRecord,
|
|
33
33
|
} from '../hitl-binding.js';
|
|
34
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
34
35
|
import type { ReviewerBinding } from '../reviewer-binding.js';
|
|
35
36
|
import { callerReviewerRole } from '../reviewer-role.js';
|
|
37
|
+
import {
|
|
38
|
+
exportActor,
|
|
39
|
+
parseSigningKeyId,
|
|
40
|
+
readExportBody,
|
|
41
|
+
signExport,
|
|
42
|
+
signExportFailure,
|
|
43
|
+
signingNotConfigured,
|
|
44
|
+
} from '../signed-export.js';
|
|
36
45
|
import type { AppEnv } from '../types.js';
|
|
37
|
-
import { clampLimit } from './pagination.js';
|
|
46
|
+
import { clampLimit, decodeCursor, encodeCursor, isCursorTime } from './pagination.js';
|
|
38
47
|
import { parseListScope } from './scope-params.js';
|
|
39
48
|
|
|
40
49
|
const APPROVAL_STATUSES: ReadonlySet<ApprovalStatus> = new Set([
|
|
@@ -73,11 +82,18 @@ const DECIDED_STATUSES: ReadonlySet<ApprovalStatus> = new Set([
|
|
|
73
82
|
'withdrawn',
|
|
74
83
|
]);
|
|
75
84
|
|
|
76
|
-
/**
|
|
77
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Audit-bundle body schema version — bump when the bundle wire shape changes.
|
|
87
|
+
* 2.0.0: a string like the other exports' (was the integer 1), named
|
|
88
|
+
* `bundleSchemaVersion` in the body too, `exportedAt` signed once.
|
|
89
|
+
*/
|
|
90
|
+
const AUDIT_BUNDLE_SCHEMA_VERSION = '2.0.0';
|
|
78
91
|
|
|
79
92
|
export interface ApprovalsRouterOptions {
|
|
80
|
-
|
|
93
|
+
/** Signs audit bundles. Absent: `POST /:approvalId/audit-bundle` answers `404 signing-not-configured`. */
|
|
94
|
+
readonly exportSigning?: ExportSigningBinding;
|
|
95
|
+
/** Records each signed export (`export-signed`). */
|
|
96
|
+
readonly auditEvents?: AuditEventBinding;
|
|
81
97
|
/**
|
|
82
98
|
* When supplied, the POST /:approvalId/complete handler
|
|
83
99
|
* invokes `runHandler.resumeRun(runId)` INLINE after `completeToken`
|
|
@@ -111,11 +127,34 @@ export function approvalsRouter(
|
|
|
111
127
|
hitlBinding: HitlBinding,
|
|
112
128
|
runBinding: RunBinding,
|
|
113
129
|
options: ApprovalsRouterOptions = {},
|
|
130
|
+
/**
|
|
131
|
+
* With one (T243 A): on top of the reviewer role, a caller sees and
|
|
132
|
+
* decides only approvals whose project it may read (the approval's, or
|
|
133
|
+
* its run's). Another project's approval is not found, as one above the
|
|
134
|
+
* caller's tier is.
|
|
135
|
+
*/
|
|
136
|
+
authorizer?: Authorizer,
|
|
114
137
|
): Hono<AppEnv> {
|
|
115
138
|
const r = new Hono<AppEnv>();
|
|
116
|
-
const
|
|
139
|
+
const { exportSigning, auditEvents } = options;
|
|
117
140
|
const runHandler = options.runHandler;
|
|
118
141
|
|
|
142
|
+
/** What an approval is checked on: its project, else its run's, else the tenant. */
|
|
143
|
+
const approvalRef = async (tenantId: TenantId, approval: Approval): Promise<ResourceRef> => {
|
|
144
|
+
if (approval.projectId !== undefined) {
|
|
145
|
+
return ref('project', approval.projectId as unknown as string);
|
|
146
|
+
}
|
|
147
|
+
const runId = approval.provenanceRef?.runId;
|
|
148
|
+
const run = runId === undefined ? null : await runBinding.getRun(tenantId, runId as never);
|
|
149
|
+
return run === null
|
|
150
|
+
? ref('tenant', tenantId as unknown as string)
|
|
151
|
+
: ref('project', run.projectId as unknown as string);
|
|
152
|
+
};
|
|
153
|
+
/** Whether the caller may read the approval's project (always, without an authorizer). */
|
|
154
|
+
const mayRead = async (c: Context<AppEnv>, approval: Approval): Promise<boolean> =>
|
|
155
|
+
authorizer === undefined ||
|
|
156
|
+
authorizer.can(c, 'read', await approvalRef(c.get('tenantId') as TenantId, approval));
|
|
157
|
+
|
|
119
158
|
// ---------- role gate for the whole resource ----------
|
|
120
159
|
// A reviewer: a token that carries a role, or whose user the roster
|
|
121
160
|
// names (a session or API key of a registered reviewer).
|
|
@@ -235,10 +274,19 @@ export function approvalsRouter(
|
|
|
235
274
|
);
|
|
236
275
|
}
|
|
237
276
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
277
|
+
// The cursor: where the last page ended (an approval's exact
|
|
278
|
+
// `createdAt` and its id), or a bare time from before that (milliseconds,
|
|
279
|
+
// no tie-breaker), which still answers as it did.
|
|
280
|
+
const rawCursor = c.req.query('cursor');
|
|
281
|
+
let after: ApprovalPosition | undefined;
|
|
282
|
+
let cursor: string | undefined;
|
|
283
|
+
if (rawCursor !== undefined && rawCursor.length > 0) {
|
|
284
|
+
const decoded = decodeCursor(rawCursor);
|
|
285
|
+
if (decoded !== null && isCursorTime(decoded.createdAt)) {
|
|
286
|
+
after = { createdAt: decoded.createdAt, id: decoded.id as unknown as ApprovalId };
|
|
287
|
+
} else if (decoded === null && Number.isFinite(Date.parse(rawCursor))) {
|
|
288
|
+
cursor = rawCursor;
|
|
289
|
+
} else {
|
|
242
290
|
c.status(statusFor('bad-input') as never);
|
|
243
291
|
return c.json(
|
|
244
292
|
toWireError({ code: 'bad-input', message: '`cursor` is malformed' }, requestId),
|
|
@@ -246,10 +294,9 @@ export function approvalsRouter(
|
|
|
246
294
|
}
|
|
247
295
|
}
|
|
248
296
|
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
// own cursor) also tell us `hasMore`.
|
|
297
|
+
// Over-fetch up to 4× the page size (capped at 500) so a page still
|
|
298
|
+
// fills when role-scoping filters rows out; the extra rows (or the
|
|
299
|
+
// binding's own cursor) also tell us `hasMore`.
|
|
253
300
|
const HITL_LIMIT_CAP = Math.min(limit * 4, 500);
|
|
254
301
|
const listInput = {
|
|
255
302
|
tenantId,
|
|
@@ -258,7 +305,8 @@ export function approvalsRouter(
|
|
|
258
305
|
...(statusFilter !== undefined && { status: statusFilter }),
|
|
259
306
|
...(requiredRoleFilter !== undefined && { requiredRole: requiredRoleFilter }),
|
|
260
307
|
...(createdAfterIso !== undefined && { since: createdAfterIso as unknown as Timestamp }),
|
|
261
|
-
...(
|
|
308
|
+
...(after !== undefined && { after }),
|
|
309
|
+
...(cursor !== undefined && { cursor: cursor as Cursor }),
|
|
262
310
|
...(waitTokenIds.length > 0 && { waitTokenIds }),
|
|
263
311
|
};
|
|
264
312
|
const listed = await hitlBinding.listApprovals(listInput);
|
|
@@ -267,14 +315,32 @@ export function approvalsRouter(
|
|
|
267
315
|
return c.json(toWireError(listed.error as never, requestId));
|
|
268
316
|
}
|
|
269
317
|
const roleRank = REVIEWER_ROLE_RANK[role];
|
|
270
|
-
const
|
|
318
|
+
const inTier = listed.value.approvals.filter(
|
|
271
319
|
(a) => REVIEWER_ROLE_RANK[a.requiredRole] <= roleRank,
|
|
272
320
|
);
|
|
321
|
+
let visible = inTier;
|
|
322
|
+
if (authorizer !== undefined) {
|
|
323
|
+
const refs = await Promise.all(inTier.map((a) => approvalRef(tenantId, a)));
|
|
324
|
+
const readable = await authorizer.filterByCan(
|
|
325
|
+
c,
|
|
326
|
+
'read',
|
|
327
|
+
inTier.map((approval, i) => ({ approval, at: refs[i] as ResourceRef })),
|
|
328
|
+
(row) => row.at,
|
|
329
|
+
);
|
|
330
|
+
visible = readable.map((row) => row.approval);
|
|
331
|
+
}
|
|
273
332
|
const page = visible.slice(0, limit);
|
|
274
333
|
const hasMore = visible.length > limit || listed.value.nextCursor !== undefined;
|
|
275
334
|
const last = page[page.length - 1];
|
|
335
|
+
// Continue after the last approval shown: at its exact `createdAt` when
|
|
336
|
+
// the binding gives it, else (a binding from before) at its time.
|
|
337
|
+
const exact = last !== undefined ? listed.value.exactCreatedAt?.[last.id] : undefined;
|
|
276
338
|
const nextCursor =
|
|
277
|
-
hasMore
|
|
339
|
+
!hasMore || last === undefined
|
|
340
|
+
? undefined
|
|
341
|
+
: exact !== undefined
|
|
342
|
+
? encodeCursor({ createdAt: exact, id: last.id as unknown as string })
|
|
343
|
+
: (last.createdAt as unknown as string);
|
|
278
344
|
return c.json({
|
|
279
345
|
data: page.map(serializeApproval),
|
|
280
346
|
hasMore,
|
|
@@ -297,7 +363,10 @@ export function approvalsRouter(
|
|
|
297
363
|
const approval = got.value;
|
|
298
364
|
// Out-of-scope reads are 404 (per API-ROUTE-CONVENTIONS.md §2.4 —
|
|
299
365
|
// avoid leaking existence across role tiers).
|
|
300
|
-
if (
|
|
366
|
+
if (
|
|
367
|
+
REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
|
|
368
|
+
!(await mayRead(c, approval))
|
|
369
|
+
) {
|
|
301
370
|
c.status(statusFor('approval-not-found') as never);
|
|
302
371
|
return c.json(
|
|
303
372
|
toWireError(
|
|
@@ -356,7 +425,10 @@ export function approvalsRouter(
|
|
|
356
425
|
return c.json(toWireError(found.error as never, requestId));
|
|
357
426
|
}
|
|
358
427
|
const approval = found.value;
|
|
359
|
-
if (
|
|
428
|
+
if (
|
|
429
|
+
REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
|
|
430
|
+
!(await mayRead(c, approval))
|
|
431
|
+
) {
|
|
360
432
|
c.status(statusFor('approval-not-found') as never);
|
|
361
433
|
return c.json(
|
|
362
434
|
toWireError(
|
|
@@ -468,7 +540,13 @@ export function approvalsRouter(
|
|
|
468
540
|
// whose run couldn't go on (a tool version it started with is gone,
|
|
469
541
|
// say) isn't reported as plain success.
|
|
470
542
|
if (runHandler !== undefined) {
|
|
471
|
-
|
|
543
|
+
const trace = c.get('trace');
|
|
544
|
+
resume = await resumeInline(
|
|
545
|
+
runHandler,
|
|
546
|
+
tenantId,
|
|
547
|
+
approval.provenanceRef.runId as RunId,
|
|
548
|
+
trace !== undefined ? { traceId: trace.traceId, spanId: trace.spanId } : undefined,
|
|
549
|
+
);
|
|
472
550
|
}
|
|
473
551
|
}
|
|
474
552
|
|
|
@@ -492,36 +570,10 @@ export function approvalsRouter(
|
|
|
492
570
|
const role = c.get('reviewerRole') as ReviewerRole;
|
|
493
571
|
const approvalId = c.req.param('approvalId') as ApprovalId;
|
|
494
572
|
|
|
495
|
-
if (
|
|
496
|
-
c.status(statusFor('signing-not-configured') as never);
|
|
497
|
-
return c.json(
|
|
498
|
-
toWireError(
|
|
499
|
-
{
|
|
500
|
-
code: 'signing-not-configured',
|
|
501
|
-
message:
|
|
502
|
-
'This deployment does not have a `signingKey` binding mounted; signed audit bundles are unavailable.',
|
|
503
|
-
},
|
|
504
|
-
requestId,
|
|
505
|
-
),
|
|
506
|
-
);
|
|
507
|
-
}
|
|
573
|
+
if (exportSigning === undefined) return signingNotConfigured(c, 'signed audit bundles');
|
|
508
574
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
body = await c.req.json();
|
|
512
|
-
} catch {
|
|
513
|
-
c.status(statusFor('bad-input') as never);
|
|
514
|
-
return c.json(
|
|
515
|
-
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
519
|
-
c.status(statusFor('bad-input') as never);
|
|
520
|
-
return c.json(
|
|
521
|
-
toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
const parsed = parseAuditBundleBody(body as Record<string, unknown>);
|
|
575
|
+
const read = await readExportBody(c);
|
|
576
|
+
const parsed = read.kind === 'ok' ? parseAuditBundleBody(read.value) : read;
|
|
525
577
|
if (parsed.kind === 'err') {
|
|
526
578
|
c.status(statusFor('bad-input') as never);
|
|
527
579
|
return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
|
|
@@ -535,7 +587,10 @@ export function approvalsRouter(
|
|
|
535
587
|
return c.json(toWireError(found.error as never, requestId));
|
|
536
588
|
}
|
|
537
589
|
const approval = found.value;
|
|
538
|
-
if (
|
|
590
|
+
if (
|
|
591
|
+
REVIEWER_ROLE_RANK[approval.requiredRole] > REVIEWER_ROLE_RANK[role] ||
|
|
592
|
+
!(await mayRead(c, approval))
|
|
593
|
+
) {
|
|
539
594
|
c.status(statusFor('approval-not-found') as never);
|
|
540
595
|
return c.json(
|
|
541
596
|
toWireError(
|
|
@@ -596,96 +651,54 @@ export function approvalsRouter(
|
|
|
596
651
|
messages = [];
|
|
597
652
|
}
|
|
598
653
|
|
|
599
|
-
// 5.
|
|
600
|
-
const privateKey = signingKey.getPrivateKey(signingKeyId);
|
|
601
|
-
if (privateKey === null) {
|
|
602
|
-
c.status(statusFor('signing-key-not-found') as never);
|
|
603
|
-
return c.json(
|
|
604
|
-
toWireError(
|
|
605
|
-
{
|
|
606
|
-
code: 'signing-key-not-found',
|
|
607
|
-
message: `No signing key registered with id "${signingKeyId as unknown as string}"`,
|
|
608
|
-
signingKeyId: signingKeyId as unknown as string,
|
|
609
|
-
},
|
|
610
|
-
requestId,
|
|
611
|
-
),
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
const publicKeyRaw = signingKey.getPublicKey(signingKeyId);
|
|
615
|
-
if (publicKeyRaw === null) {
|
|
616
|
-
c.status(statusFor('signing-key-not-found') as never);
|
|
617
|
-
return c.json(
|
|
618
|
-
toWireError(
|
|
619
|
-
{
|
|
620
|
-
code: 'signing-key-not-found',
|
|
621
|
-
message: `Signing key "${signingKeyId as unknown as string}" resolved a private key but no public key`,
|
|
622
|
-
signingKeyId: signingKeyId as unknown as string,
|
|
623
|
-
},
|
|
624
|
-
requestId,
|
|
625
|
-
),
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// 6. Build the canonical bundle body.
|
|
654
|
+
// 5. Sign the bundle body (and record the export).
|
|
630
655
|
const guardrailResults = extractGuardrailResults(approval.context);
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
subjectKind: approval.subjectKind,
|
|
636
|
-
subjectRef: approval.subjectRef,
|
|
637
|
-
requiredRole: approval.requiredRole,
|
|
638
|
-
status: approval.status,
|
|
639
|
-
createdAt: approval.createdAt as unknown as string,
|
|
640
|
-
...(approval.decidedAt !== undefined && {
|
|
641
|
-
decidedAt: approval.decidedAt as unknown as string,
|
|
642
|
-
}),
|
|
643
|
-
decision:
|
|
644
|
-
decisionRow !== null
|
|
645
|
-
? {
|
|
646
|
-
kind: decisionRow.decision,
|
|
647
|
-
reviewerId: decisionRow.reviewerId,
|
|
648
|
-
reviewerRoleAtDecision: decisionRow.reviewerRoleAtDecision,
|
|
649
|
-
decidedAt: decisionRow.decidedAt as unknown as string,
|
|
650
|
-
...(decisionRow.rationale !== undefined && { rationale: decisionRow.rationale }),
|
|
651
|
-
}
|
|
652
|
-
: null,
|
|
653
|
-
evidence: {
|
|
654
|
-
...(guardrailResults !== undefined && { guardrailResults }),
|
|
655
|
-
...(messages !== undefined && { messages }),
|
|
656
|
-
},
|
|
657
|
-
exportedAt: new Date().toISOString(),
|
|
658
|
-
};
|
|
659
|
-
const canonicalBundleBytes = new TextEncoder().encode(canonicalize(bundleBody));
|
|
660
|
-
|
|
661
|
-
// 7. Sign.
|
|
662
|
-
const signResult = signEd25519(privateKey, canonicalBundleBytes);
|
|
663
|
-
if (signResult.kind === 'err') {
|
|
664
|
-
c.status(statusFor('export-key-error') as never);
|
|
665
|
-
return c.json(
|
|
666
|
-
toWireError(
|
|
667
|
-
{
|
|
668
|
-
code: 'export-key-error',
|
|
669
|
-
message: `Failed to sign audit bundle: ${signResult.error.message}`,
|
|
670
|
-
},
|
|
671
|
-
requestId,
|
|
672
|
-
),
|
|
673
|
-
);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
return c.json({
|
|
677
|
-
approvalId: approvalId as unknown as string,
|
|
678
|
-
bundle: Buffer.from(canonicalBundleBytes).toString('base64'),
|
|
656
|
+
const runId = approval.provenanceRef?.runId as unknown as string | undefined;
|
|
657
|
+
const signed = await signExport({
|
|
658
|
+
signer: exportSigning,
|
|
659
|
+
kind: 'audit-bundle',
|
|
679
660
|
bundleSchemaVersion: AUDIT_BUNDLE_SCHEMA_VERSION,
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
661
|
+
...(signingKeyId !== undefined && { signingKeyId }),
|
|
662
|
+
body: {
|
|
663
|
+
approvalId: approval.id as unknown as string,
|
|
664
|
+
tenantId: approval.tenantId as unknown as string,
|
|
665
|
+
subjectKind: approval.subjectKind,
|
|
666
|
+
subjectRef: approval.subjectRef,
|
|
667
|
+
requiredRole: approval.requiredRole,
|
|
668
|
+
status: approval.status,
|
|
669
|
+
createdAt: approval.createdAt as unknown as string,
|
|
670
|
+
...(approval.decidedAt !== undefined && {
|
|
671
|
+
decidedAt: approval.decidedAt as unknown as string,
|
|
672
|
+
}),
|
|
673
|
+
decision:
|
|
674
|
+
decisionRow !== null
|
|
675
|
+
? {
|
|
676
|
+
kind: decisionRow.decision,
|
|
677
|
+
reviewerId: decisionRow.reviewerId,
|
|
678
|
+
reviewerRoleAtDecision: decisionRow.reviewerRoleAtDecision,
|
|
679
|
+
decidedAt: decisionRow.decidedAt as unknown as string,
|
|
680
|
+
...(decisionRow.rationale !== undefined && { rationale: decisionRow.rationale }),
|
|
681
|
+
}
|
|
682
|
+
: null,
|
|
683
|
+
evidence: {
|
|
684
|
+
...(guardrailResults !== undefined && { guardrailResults }),
|
|
685
|
+
...(messages !== undefined && { messages }),
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
...(auditEvents !== undefined && {
|
|
689
|
+
record: {
|
|
690
|
+
auditEvents,
|
|
691
|
+
tenantId,
|
|
692
|
+
...(approval.projectId !== undefined && { projectId: approval.projectId }),
|
|
693
|
+
...(runId !== undefined && { runId }),
|
|
694
|
+
actor: exportActor(c),
|
|
695
|
+
subject: { approvalId: approval.id as unknown as string },
|
|
696
|
+
},
|
|
697
|
+
}),
|
|
686
698
|
});
|
|
699
|
+
if (signed.kind === 'err') return signExportFailure(c, signed.error, 'export-key-error');
|
|
700
|
+
return c.json({ approvalId: approvalId as unknown as string, ...signed.value });
|
|
687
701
|
});
|
|
688
|
-
|
|
689
702
|
return r;
|
|
690
703
|
}
|
|
691
704
|
|
|
@@ -800,7 +813,7 @@ function parseCompleteBody(
|
|
|
800
813
|
}
|
|
801
814
|
|
|
802
815
|
interface ParsedAuditBundle {
|
|
803
|
-
readonly signingKeyId:
|
|
816
|
+
readonly signingKeyId: string | undefined;
|
|
804
817
|
readonly includeMessages: boolean;
|
|
805
818
|
}
|
|
806
819
|
|
|
@@ -809,10 +822,8 @@ function parseAuditBundleBody(
|
|
|
809
822
|
):
|
|
810
823
|
| { readonly kind: 'ok'; readonly value: ParsedAuditBundle }
|
|
811
824
|
| { readonly kind: 'err'; readonly message: string } {
|
|
812
|
-
const
|
|
813
|
-
if (
|
|
814
|
-
return { kind: 'err', message: 'Field `signingKeyId` must be a non-empty string' };
|
|
815
|
-
}
|
|
825
|
+
const signingKeyId = parseSigningKeyId(body);
|
|
826
|
+
if (signingKeyId.kind === 'err') return signingKeyId;
|
|
816
827
|
let includeMessages = false;
|
|
817
828
|
if ('includeMessages' in body) {
|
|
818
829
|
const im = body.includeMessages;
|
|
@@ -821,13 +832,7 @@ function parseAuditBundleBody(
|
|
|
821
832
|
}
|
|
822
833
|
includeMessages = im;
|
|
823
834
|
}
|
|
824
|
-
return {
|
|
825
|
-
kind: 'ok',
|
|
826
|
-
value: {
|
|
827
|
-
signingKeyId: raw as SigningKeyId,
|
|
828
|
-
includeMessages,
|
|
829
|
-
},
|
|
830
|
-
};
|
|
835
|
+
return { kind: 'ok', value: { signingKeyId: signingKeyId.value, includeMessages } };
|
|
831
836
|
}
|
|
832
837
|
|
|
833
838
|
/** How the inline resume after a decision went. */
|
|
@@ -844,9 +849,14 @@ async function resumeInline(
|
|
|
844
849
|
runHandler: RunHandlerBinding,
|
|
845
850
|
tenantId: TenantId,
|
|
846
851
|
runId: RunId,
|
|
852
|
+
trace: RunTrace | undefined,
|
|
847
853
|
): Promise<ResumeReport> {
|
|
848
854
|
try {
|
|
849
|
-
const outcome = await runHandler.resumeRun({
|
|
855
|
+
const outcome = await runHandler.resumeRun({
|
|
856
|
+
tenantId,
|
|
857
|
+
runId,
|
|
858
|
+
...(trace !== undefined && { trace }),
|
|
859
|
+
});
|
|
850
860
|
return outcome.kind === 'ok'
|
|
851
861
|
? { kind: 'ok' }
|
|
852
862
|
: { kind: 'failed', code: outcome.error.code, message: outcome.error.message };
|