@kindgi/api 0.0.0-bootstrap.0 → 0.1.1
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/LICENSE +201 -0
- package/README.md +216 -1
- package/dist/adapter-binding.d.ts +177 -0
- package/dist/adapter-binding.d.ts.map +1 -0
- package/dist/adapter-binding.js +12 -0
- package/dist/adapter-binding.js.map +1 -0
- package/dist/agent-binding.d.ts +207 -0
- package/dist/agent-binding.d.ts.map +1 -0
- package/dist/agent-binding.js +4 -0
- package/dist/agent-binding.js.map +1 -0
- package/dist/app.d.ts +770 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +397 -0
- package/dist/app.js.map +1 -0
- package/dist/capability-binding.d.ts +76 -0
- package/dist/capability-binding.d.ts.map +1 -0
- package/dist/capability-binding.js +4 -0
- package/dist/capability-binding.js.map +1 -0
- package/dist/cost-binding.d.ts +175 -0
- package/dist/cost-binding.d.ts.map +1 -0
- package/dist/cost-binding.js +13 -0
- package/dist/cost-binding.js.map +1 -0
- package/dist/deployment-binding.d.ts +201 -0
- package/dist/deployment-binding.d.ts.map +1 -0
- package/dist/deployment-binding.js +4 -0
- package/dist/deployment-binding.js.map +1 -0
- package/dist/env-binding.d.ts +132 -0
- package/dist/env-binding.d.ts.map +1 -0
- package/dist/env-binding.js +4 -0
- package/dist/env-binding.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +268 -0
- package/dist/errors.js.map +1 -0
- package/dist/eval-run-binding.d.ts +196 -0
- package/dist/eval-run-binding.d.ts.map +1 -0
- package/dist/eval-run-binding.js +16 -0
- package/dist/eval-run-binding.js.map +1 -0
- package/dist/eval-run-dispatcher.d.ts +131 -0
- package/dist/eval-run-dispatcher.d.ts.map +1 -0
- package/dist/eval-run-dispatcher.js +368 -0
- package/dist/eval-run-dispatcher.js.map +1 -0
- package/dist/eval-suite-binding.d.ts +227 -0
- package/dist/eval-suite-binding.d.ts.map +1 -0
- package/dist/eval-suite-binding.js +24 -0
- package/dist/eval-suite-binding.js.map +1 -0
- package/dist/event-bus-binding.d.ts +107 -0
- package/dist/event-bus-binding.d.ts.map +1 -0
- package/dist/event-bus-binding.js +5 -0
- package/dist/event-bus-binding.js.map +1 -0
- package/dist/flow-binding.d.ts +194 -0
- package/dist/flow-binding.d.ts.map +1 -0
- package/dist/flow-binding.js +4 -0
- package/dist/flow-binding.js.map +1 -0
- package/dist/guardrail-binding.d.ts +138 -0
- package/dist/guardrail-binding.d.ts.map +1 -0
- package/dist/guardrail-binding.js +4 -0
- package/dist/guardrail-binding.js.map +1 -0
- package/dist/handler-binding.d.ts +126 -0
- package/dist/handler-binding.d.ts.map +1 -0
- package/dist/handler-binding.js +4 -0
- package/dist/handler-binding.js.map +1 -0
- package/dist/hitl-binding.d.ts +115 -0
- package/dist/hitl-binding.d.ts.map +1 -0
- package/dist/hitl-binding.js +4 -0
- package/dist/hitl-binding.js.map +1 -0
- package/dist/identity-directory-binding.d.ts +116 -0
- package/dist/identity-directory-binding.d.ts.map +1 -0
- package/dist/identity-directory-binding.js +4 -0
- package/dist/identity-directory-binding.js.map +1 -0
- package/dist/identity-provider-binding.d.ts +184 -0
- package/dist/identity-provider-binding.d.ts.map +1 -0
- package/dist/identity-provider-binding.js +4 -0
- package/dist/identity-provider-binding.js.map +1 -0
- package/dist/image-registry-binding.d.ts +165 -0
- package/dist/image-registry-binding.d.ts.map +1 -0
- package/dist/image-registry-binding.js +4 -0
- package/dist/image-registry-binding.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/key-management-binding.d.ts +101 -0
- package/dist/key-management-binding.d.ts.map +1 -0
- package/dist/key-management-binding.js +4 -0
- package/dist/key-management-binding.js.map +1 -0
- package/dist/mcp-endpoint-binding.d.ts +312 -0
- package/dist/mcp-endpoint-binding.d.ts.map +1 -0
- package/dist/mcp-endpoint-binding.js +12 -0
- package/dist/mcp-endpoint-binding.js.map +1 -0
- package/dist/memory-binding.d.ts +209 -0
- package/dist/memory-binding.d.ts.map +1 -0
- package/dist/memory-binding.js +4 -0
- package/dist/memory-binding.js.map +1 -0
- package/dist/middleware/auth.d.ts +168 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +247 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/authorize.d.ts +26 -0
- package/dist/middleware/authorize.d.ts.map +1 -0
- package/dist/middleware/authorize.js +65 -0
- package/dist/middleware/authorize.js.map +1 -0
- package/dist/middleware/error-mapper.d.ts +20 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -0
- package/dist/middleware/error-mapper.js +34 -0
- package/dist/middleware/error-mapper.js.map +1 -0
- package/dist/middleware/idempotency.d.ts +43 -0
- package/dist/middleware/idempotency.d.ts.map +1 -0
- package/dist/middleware/idempotency.js +118 -0
- package/dist/middleware/idempotency.js.map +1 -0
- package/dist/middleware/principal.d.ts +4 -0
- package/dist/middleware/principal.d.ts.map +1 -0
- package/dist/middleware/principal.js +42 -0
- package/dist/middleware/principal.js.map +1 -0
- package/dist/middleware/public-run-routes.d.ts +16 -0
- package/dist/middleware/public-run-routes.d.ts.map +1 -0
- package/dist/middleware/public-run-routes.js +43 -0
- package/dist/middleware/public-run-routes.js.map +1 -0
- package/dist/middleware/request-id.d.ts +14 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +24 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/sigv4-verify.d.ts +64 -0
- package/dist/middleware/sigv4-verify.d.ts.map +1 -0
- package/dist/middleware/sigv4-verify.js +286 -0
- package/dist/middleware/sigv4-verify.js.map +1 -0
- package/dist/middleware/sigv4.d.ts +25 -0
- package/dist/middleware/sigv4.d.ts.map +1 -0
- package/dist/middleware/sigv4.js +120 -0
- package/dist/middleware/sigv4.js.map +1 -0
- package/dist/openapi/generate.d.ts +15 -0
- package/dist/openapi/generate.d.ts.map +1 -0
- package/dist/openapi/generate.js +241 -0
- package/dist/openapi/generate.js.map +1 -0
- package/dist/openapi/operations.d.ts +70 -0
- package/dist/openapi/operations.d.ts.map +1 -0
- package/dist/openapi/operations.js +5050 -0
- package/dist/openapi/operations.js.map +1 -0
- package/dist/openapi/schemas.d.ts +590 -0
- package/dist/openapi/schemas.d.ts.map +1 -0
- package/dist/openapi/schemas.js +5820 -0
- package/dist/openapi/schemas.js.map +1 -0
- package/dist/provenance-binding.d.ts +116 -0
- package/dist/provenance-binding.d.ts.map +1 -0
- package/dist/provenance-binding.js +31 -0
- package/dist/provenance-binding.js.map +1 -0
- package/dist/provider-binding.d.ts +174 -0
- package/dist/provider-binding.d.ts.map +1 -0
- package/dist/provider-binding.js +4 -0
- package/dist/provider-binding.js.map +1 -0
- package/dist/public-run-token.d.ts +97 -0
- package/dist/public-run-token.d.ts.map +1 -0
- package/dist/public-run-token.js +167 -0
- package/dist/public-run-token.js.map +1 -0
- package/dist/retention-binding.d.ts +69 -0
- package/dist/retention-binding.d.ts.map +1 -0
- package/dist/retention-binding.js +4 -0
- package/dist/retention-binding.js.map +1 -0
- package/dist/reviewer-binding.d.ts +84 -0
- package/dist/reviewer-binding.d.ts.map +1 -0
- package/dist/reviewer-binding.js +4 -0
- package/dist/reviewer-binding.js.map +1 -0
- package/dist/rotation-status-store.d.ts +96 -0
- package/dist/rotation-status-store.d.ts.map +1 -0
- package/dist/rotation-status-store.js +106 -0
- package/dist/rotation-status-store.js.map +1 -0
- package/dist/routes/adapters.d.ts +29 -0
- package/dist/routes/adapters.d.ts.map +1 -0
- package/dist/routes/adapters.js +230 -0
- package/dist/routes/adapters.js.map +1 -0
- package/dist/routes/agents.d.ts +17 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +342 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/approvals.d.ts +37 -0
- package/dist/routes/approvals.d.ts.map +1 -0
- package/dist/routes/approvals.js +551 -0
- package/dist/routes/approvals.js.map +1 -0
- package/dist/routes/artifacts.d.ts +25 -0
- package/dist/routes/artifacts.d.ts.map +1 -0
- package/dist/routes/artifacts.js +265 -0
- package/dist/routes/artifacts.js.map +1 -0
- package/dist/routes/audit.d.ts +6 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +162 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/auth.d.ts +47 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +630 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/capabilities.d.ts +14 -0
- package/dist/routes/capabilities.d.ts.map +1 -0
- package/dist/routes/capabilities.js +62 -0
- package/dist/routes/capabilities.js.map +1 -0
- package/dist/routes/compliance.d.ts +37 -0
- package/dist/routes/compliance.d.ts.map +1 -0
- package/dist/routes/compliance.js +321 -0
- package/dist/routes/compliance.js.map +1 -0
- package/dist/routes/conversations.d.ts +13 -0
- package/dist/routes/conversations.d.ts.map +1 -0
- package/dist/routes/conversations.js +295 -0
- package/dist/routes/conversations.js.map +1 -0
- package/dist/routes/cost.d.ts +24 -0
- package/dist/routes/cost.d.ts.map +1 -0
- package/dist/routes/cost.js +243 -0
- package/dist/routes/cost.js.map +1 -0
- package/dist/routes/deployments.d.ts +122 -0
- package/dist/routes/deployments.d.ts.map +1 -0
- package/dist/routes/deployments.js +1036 -0
- package/dist/routes/deployments.js.map +1 -0
- package/dist/routes/env.d.ts +62 -0
- package/dist/routes/env.d.ts.map +1 -0
- package/dist/routes/env.js +311 -0
- package/dist/routes/env.js.map +1 -0
- package/dist/routes/eval-runs.d.ts +28 -0
- package/dist/routes/eval-runs.d.ts.map +1 -0
- package/dist/routes/eval-runs.js +479 -0
- package/dist/routes/eval-runs.js.map +1 -0
- package/dist/routes/eval-suites.d.ts +24 -0
- package/dist/routes/eval-suites.d.ts.map +1 -0
- package/dist/routes/eval-suites.js +381 -0
- package/dist/routes/eval-suites.js.map +1 -0
- package/dist/routes/event-triggers.d.ts +12 -0
- package/dist/routes/event-triggers.d.ts.map +1 -0
- package/dist/routes/event-triggers.js +218 -0
- package/dist/routes/event-triggers.js.map +1 -0
- package/dist/routes/flows.d.ts +23 -0
- package/dist/routes/flows.d.ts.map +1 -0
- package/dist/routes/flows.js +344 -0
- package/dist/routes/flows.js.map +1 -0
- package/dist/routes/guardrails.d.ts +33 -0
- package/dist/routes/guardrails.d.ts.map +1 -0
- package/dist/routes/guardrails.js +236 -0
- package/dist/routes/guardrails.js.map +1 -0
- package/dist/routes/identity.d.ts +39 -0
- package/dist/routes/identity.d.ts.map +1 -0
- package/dist/routes/identity.js +138 -0
- package/dist/routes/identity.js.map +1 -0
- package/dist/routes/mcp.d.ts +23 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +727 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/memory.d.ts +16 -0
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +353 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/observations.d.ts +19 -0
- package/dist/routes/observations.d.ts.map +1 -0
- package/dist/routes/observations.js +135 -0
- package/dist/routes/observations.js.map +1 -0
- package/dist/routes/orgs.d.ts +24 -0
- package/dist/routes/orgs.d.ts.map +1 -0
- package/dist/routes/orgs.js +208 -0
- package/dist/routes/orgs.js.map +1 -0
- package/dist/routes/pagination.d.ts +18 -0
- package/dist/routes/pagination.d.ts.map +1 -0
- package/dist/routes/pagination.js +35 -0
- package/dist/routes/pagination.js.map +1 -0
- package/dist/routes/policies.d.ts +23 -0
- package/dist/routes/policies.d.ts.map +1 -0
- package/dist/routes/policies.js +314 -0
- package/dist/routes/policies.js.map +1 -0
- package/dist/routes/projects.d.ts +45 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +485 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/proposals.d.ts +24 -0
- package/dist/routes/proposals.d.ts.map +1 -0
- package/dist/routes/proposals.js +581 -0
- package/dist/routes/proposals.js.map +1 -0
- package/dist/routes/provenance.d.ts +34 -0
- package/dist/routes/provenance.d.ts.map +1 -0
- package/dist/routes/provenance.js +274 -0
- package/dist/routes/provenance.js.map +1 -0
- package/dist/routes/providers.d.ts +32 -0
- package/dist/routes/providers.d.ts.map +1 -0
- package/dist/routes/providers.js +490 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/public-run-tokens.d.ts +17 -0
- package/dist/routes/public-run-tokens.d.ts.map +1 -0
- package/dist/routes/public-run-tokens.js +69 -0
- package/dist/routes/public-run-tokens.js.map +1 -0
- package/dist/routes/retention.d.ts +19 -0
- package/dist/routes/retention.d.ts.map +1 -0
- package/dist/routes/retention.js +152 -0
- package/dist/routes/retention.js.map +1 -0
- package/dist/routes/reviewers.d.ts +5 -0
- package/dist/routes/reviewers.d.ts.map +1 -0
- package/dist/routes/reviewers.js +161 -0
- package/dist/routes/reviewers.js.map +1 -0
- package/dist/routes/runs.d.ts +34 -0
- package/dist/routes/runs.d.ts.map +1 -0
- package/dist/routes/runs.js +705 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/routes/s3.d.ts +31 -0
- package/dist/routes/s3.d.ts.map +1 -0
- package/dist/routes/s3.js +433 -0
- package/dist/routes/s3.js.map +1 -0
- package/dist/routes/schedules.d.ts +20 -0
- package/dist/routes/schedules.d.ts.map +1 -0
- package/dist/routes/schedules.js +234 -0
- package/dist/routes/schedules.js.map +1 -0
- package/dist/routes/scope-params.d.ts +57 -0
- package/dist/routes/scope-params.d.ts.map +1 -0
- package/dist/routes/scope-params.js +105 -0
- package/dist/routes/scope-params.js.map +1 -0
- package/dist/routes/secret-ref.d.ts +20 -0
- package/dist/routes/secret-ref.d.ts.map +1 -0
- package/dist/routes/secret-ref.js +42 -0
- package/dist/routes/secret-ref.js.map +1 -0
- package/dist/routes/secrets.d.ts +53 -0
- package/dist/routes/secrets.d.ts.map +1 -0
- package/dist/routes/secrets.js +715 -0
- package/dist/routes/secrets.js.map +1 -0
- package/dist/routes/signing-keys.d.ts +23 -0
- package/dist/routes/signing-keys.d.ts.map +1 -0
- package/dist/routes/signing-keys.js +212 -0
- package/dist/routes/signing-keys.js.map +1 -0
- package/dist/routes/sse.d.ts +58 -0
- package/dist/routes/sse.d.ts.map +1 -0
- package/dist/routes/sse.js +92 -0
- package/dist/routes/sse.js.map +1 -0
- package/dist/routes/teams.d.ts +30 -0
- package/dist/routes/teams.d.ts.map +1 -0
- package/dist/routes/teams.js +443 -0
- package/dist/routes/teams.js.map +1 -0
- package/dist/routes/tenant.d.ts +57 -0
- package/dist/routes/tenant.d.ts.map +1 -0
- package/dist/routes/tenant.js +352 -0
- package/dist/routes/tenant.js.map +1 -0
- package/dist/routes/tokens.d.ts +14 -0
- package/dist/routes/tokens.d.ts.map +1 -0
- package/dist/routes/tokens.js +231 -0
- package/dist/routes/tokens.js.map +1 -0
- package/dist/routes/tools.d.ts +33 -0
- package/dist/routes/tools.d.ts.map +1 -0
- package/dist/routes/tools.js +380 -0
- package/dist/routes/tools.js.map +1 -0
- package/dist/routes/webhook-endpoints.d.ts +10 -0
- package/dist/routes/webhook-endpoints.d.ts.map +1 -0
- package/dist/routes/webhook-endpoints.js +407 -0
- package/dist/routes/webhook-endpoints.js.map +1 -0
- package/dist/routes/webhooks.d.ts +21 -0
- package/dist/routes/webhooks.d.ts.map +1 -0
- package/dist/routes/webhooks.js +228 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/s3-credential-binding.d.ts +54 -0
- package/dist/s3-credential-binding.d.ts.map +1 -0
- package/dist/s3-credential-binding.js +4 -0
- package/dist/s3-credential-binding.js.map +1 -0
- package/dist/secrets-binding.d.ts +281 -0
- package/dist/secrets-binding.d.ts.map +1 -0
- package/dist/secrets-binding.js +10 -0
- package/dist/secrets-binding.js.map +1 -0
- package/dist/secrets-provider-binding.d.ts +164 -0
- package/dist/secrets-provider-binding.d.ts.map +1 -0
- package/dist/secrets-provider-binding.js +4 -0
- package/dist/secrets-provider-binding.js.map +1 -0
- package/dist/session-store-binding.d.ts +148 -0
- package/dist/session-store-binding.d.ts.map +1 -0
- package/dist/session-store-binding.js +4 -0
- package/dist/session-store-binding.js.map +1 -0
- package/dist/signing-key-binding.d.ts +210 -0
- package/dist/signing-key-binding.d.ts.map +1 -0
- package/dist/signing-key-binding.js +4 -0
- package/dist/signing-key-binding.js.map +1 -0
- package/dist/state-store-binding.d.ts +53 -0
- package/dist/state-store-binding.d.ts.map +1 -0
- package/dist/state-store-binding.js +38 -0
- package/dist/state-store-binding.js.map +1 -0
- package/dist/supervisor-binding.d.ts +526 -0
- package/dist/supervisor-binding.d.ts.map +1 -0
- package/dist/supervisor-binding.js +4 -0
- package/dist/supervisor-binding.js.map +1 -0
- package/dist/tenant-host-access.d.ts +41 -0
- package/dist/tenant-host-access.d.ts.map +1 -0
- package/dist/tenant-host-access.js +42 -0
- package/dist/tenant-host-access.js.map +1 -0
- package/dist/token-admin.d.ts +99 -0
- package/dist/token-admin.d.ts.map +1 -0
- package/dist/token-admin.js +4 -0
- package/dist/token-admin.js.map +1 -0
- package/dist/tool-binding.d.ts +247 -0
- package/dist/tool-binding.d.ts.map +1 -0
- package/dist/tool-binding.js +4 -0
- package/dist/tool-binding.js.map +1 -0
- package/dist/trigger-binding.d.ts +13 -0
- package/dist/trigger-binding.d.ts.map +1 -0
- package/dist/trigger-binding.js +4 -0
- package/dist/trigger-binding.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook-endpoint-binding.d.ts +230 -0
- package/dist/webhook-endpoint-binding.d.ts.map +1 -0
- package/dist/webhook-endpoint-binding.js +12 -0
- package/dist/webhook-endpoint-binding.js.map +1 -0
- package/dist/xml.d.ts +79 -0
- package/dist/xml.d.ts.map +1 -0
- package/dist/xml.js +115 -0
- package/dist/xml.js.map +1 -0
- package/openapi.json +29649 -0
- package/package.json +76 -4
- package/scripts/emit-openapi.mjs +44 -0
- package/src/adapter-binding.ts +204 -0
- package/src/agent-binding.ts +231 -0
- package/src/app.ts +1286 -0
- package/src/capability-binding.ts +83 -0
- package/src/cost-binding.ts +213 -0
- package/src/deployment-binding.ts +225 -0
- package/src/env-binding.ts +140 -0
- package/src/errors.ts +295 -0
- package/src/eval-run-binding.ts +209 -0
- package/src/eval-run-dispatcher.ts +497 -0
- package/src/eval-suite-binding.ts +257 -0
- package/src/event-bus-binding.ts +127 -0
- package/src/flow-binding.ts +213 -0
- package/src/guardrail-binding.ts +151 -0
- package/src/handler-binding.ts +132 -0
- package/src/hitl-binding.ts +172 -0
- package/src/identity-directory-binding.ts +128 -0
- package/src/identity-provider-binding.ts +203 -0
- package/src/image-registry-binding.ts +193 -0
- package/src/index.ts +606 -0
- package/src/key-management-binding.ts +91 -0
- package/src/mcp-endpoint-binding.ts +311 -0
- package/src/memory-binding.ts +239 -0
- package/src/middleware/auth.ts +437 -0
- package/src/middleware/authorize.ts +125 -0
- package/src/middleware/error-mapper.ts +40 -0
- package/src/middleware/idempotency.ts +160 -0
- package/src/middleware/principal.ts +64 -0
- package/src/middleware/public-run-routes.ts +50 -0
- package/src/middleware/request-id.ts +28 -0
- package/src/middleware/sigv4-verify.ts +374 -0
- package/src/middleware/sigv4.ts +165 -0
- package/src/openapi/generate.ts +307 -0
- package/src/openapi/operations.ts +5444 -0
- package/src/openapi/schemas.ts +6363 -0
- package/src/provenance-binding.ts +169 -0
- package/src/provider-binding.ts +196 -0
- package/src/public-run-token.ts +263 -0
- package/src/retention-binding.ts +78 -0
- package/src/reviewer-binding.ts +99 -0
- package/src/rotation-status-store.ts +209 -0
- package/src/routes/adapters.ts +319 -0
- package/src/routes/agents.ts +424 -0
- package/src/routes/approvals.ts +759 -0
- package/src/routes/artifacts.ts +317 -0
- package/src/routes/audit.ts +219 -0
- package/src/routes/auth.ts +806 -0
- package/src/routes/capabilities.ts +79 -0
- package/src/routes/compliance.ts +482 -0
- package/src/routes/conversations.ts +369 -0
- package/src/routes/cost.ts +327 -0
- package/src/routes/deployments.ts +1493 -0
- package/src/routes/env.ts +429 -0
- package/src/routes/eval-runs.ts +631 -0
- package/src/routes/eval-suites.ts +490 -0
- package/src/routes/event-triggers.ts +283 -0
- package/src/routes/flows.ts +423 -0
- package/src/routes/guardrails.ts +320 -0
- package/src/routes/identity.ts +203 -0
- package/src/routes/mcp.ts +940 -0
- package/src/routes/memory.ts +430 -0
- package/src/routes/observations.ts +175 -0
- package/src/routes/orgs.ts +273 -0
- package/src/routes/pagination.ts +51 -0
- package/src/routes/policies.ts +413 -0
- package/src/routes/projects.ts +634 -0
- package/src/routes/proposals.ts +719 -0
- package/src/routes/provenance.ts +406 -0
- package/src/routes/providers.ts +624 -0
- package/src/routes/public-run-tokens.ts +104 -0
- package/src/routes/retention.ts +193 -0
- package/src/routes/reviewers.ts +209 -0
- package/src/routes/runs.ts +892 -0
- package/src/routes/s3.ts +519 -0
- package/src/routes/schedules.ts +300 -0
- package/src/routes/scope-params.ts +133 -0
- package/src/routes/secret-ref.ts +52 -0
- package/src/routes/secrets.ts +975 -0
- package/src/routes/signing-keys.ts +259 -0
- package/src/routes/sse.ts +148 -0
- package/src/routes/teams.ts +584 -0
- package/src/routes/tenant.ts +530 -0
- package/src/routes/tokens.ts +285 -0
- package/src/routes/tools.ts +491 -0
- package/src/routes/webhook-endpoints.ts +534 -0
- package/src/routes/webhooks.ts +296 -0
- package/src/s3-credential-binding.ts +58 -0
- package/src/secrets-binding.ts +308 -0
- package/src/secrets-provider-binding.ts +167 -0
- package/src/session-store-binding.ts +163 -0
- package/src/signing-key-binding.ts +235 -0
- package/src/state-store-binding.ts +84 -0
- package/src/supervisor-binding.ts +554 -0
- package/src/tenant-host-access.ts +62 -0
- package/src/token-admin.ts +104 -0
- package/src/tool-binding.ts +274 -0
- package/src/trigger-binding.ts +38 -0
- package/src/types.ts +74 -0
- package/src/webhook-endpoint-binding.ts +246 -0
- package/src/xml.ts +196 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
import { type Principal, ref, tuplesForCreate } from '@kindgi/authz';
|
|
7
|
+
import type { Cursor, ProjectId, TenantId, UserId } from '@kindgi/types';
|
|
8
|
+
|
|
9
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
10
|
+
import {
|
|
11
|
+
EVAL_KINDS,
|
|
12
|
+
type EvalKind,
|
|
13
|
+
type EvalSuite,
|
|
14
|
+
type EvalSuiteRegistryBinding,
|
|
15
|
+
} from '../eval-suite-binding.js';
|
|
16
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
17
|
+
import type { AppEnv } from '../types.js';
|
|
18
|
+
import { clampLimit } from './pagination.js';
|
|
19
|
+
import { parseScopeParams } from './scope-params.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Evaluation-suite resource routes — part of the admin control plane.
|
|
23
|
+
* Full versioned CRUD, mirroring
|
|
24
|
+
* `policies` 1:1.
|
|
25
|
+
*
|
|
26
|
+
* The registry is intentionally kind-neutral: the wire body carries a
|
|
27
|
+
* `kind` discriminator and a `spec` object whose shape is dictated by
|
|
28
|
+
* that kind. The route validates the top-level shape (id, tenantId,
|
|
29
|
+
* semver version, kind ∈ closed enum, spec is an object) — deeper
|
|
30
|
+
* validation of `spec` is the runtime consumer's responsibility (they
|
|
31
|
+
* own the semantics for their kind).
|
|
32
|
+
*
|
|
33
|
+
* Registry-only. Actual eval runs (dispatch to eval-judge adapters,
|
|
34
|
+
* HITL delegation for `human-review`, custom-handler dispatch via
|
|
35
|
+
* handler-as-code) live in the eval-runs surface — the same
|
|
36
|
+
* discipline that split policies (registry) from policy enforcement
|
|
37
|
+
* (consumer).
|
|
38
|
+
*/
|
|
39
|
+
export function evalSuitesRouter(
|
|
40
|
+
binding: EvalSuiteRegistryBinding,
|
|
41
|
+
authorizer?: Authorizer,
|
|
42
|
+
): Hono<AppEnv> {
|
|
43
|
+
const r = new Hono<AppEnv>();
|
|
44
|
+
|
|
45
|
+
// Authorization — same checks as the agents routes.
|
|
46
|
+
if (authorizer !== undefined) {
|
|
47
|
+
r.use('/', async (c, next) => {
|
|
48
|
+
if (c.req.method !== 'POST') return next();
|
|
49
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
50
|
+
const mw = authorizer.authorize('admin', async () => {
|
|
51
|
+
try {
|
|
52
|
+
const body = await c.req.json();
|
|
53
|
+
const pid =
|
|
54
|
+
body !== null && typeof body === 'object'
|
|
55
|
+
? (body as Record<string, unknown>).projectId
|
|
56
|
+
: undefined;
|
|
57
|
+
if (typeof pid === 'string' && pid.length > 0) return ref('project', pid);
|
|
58
|
+
} catch {
|
|
59
|
+
// POST handler validates + returns 400
|
|
60
|
+
}
|
|
61
|
+
return ref('tenant', tenantId as unknown as string);
|
|
62
|
+
});
|
|
63
|
+
return mw(c, next);
|
|
64
|
+
});
|
|
65
|
+
r.use('/', async (c, next) => {
|
|
66
|
+
if (c.req.method !== 'GET') return next();
|
|
67
|
+
// A project filter needs read on that project. Parse it as the
|
|
68
|
+
// handler does (`?scopeKind=project&scopeId=`).
|
|
69
|
+
const s = parseScopeParams((n) => c.req.query(n), {
|
|
70
|
+
tenantId: c.get('tenantId') as TenantId,
|
|
71
|
+
});
|
|
72
|
+
if (s.kind !== 'ok' || s.scope?.kind !== 'project') return next();
|
|
73
|
+
const scopeProjectId = s.scope.projectId as unknown as string;
|
|
74
|
+
const mw = authorizer.authorize('read', () => ref('project', scopeProjectId));
|
|
75
|
+
return mw(c, next);
|
|
76
|
+
});
|
|
77
|
+
r.use('/:suiteId/*', async (c, next) => {
|
|
78
|
+
const action = c.req.method === 'GET' ? 'read' : 'admin';
|
|
79
|
+
const suiteId = c.req.param('suiteId') ?? '';
|
|
80
|
+
const mw = authorizer.authorize(action, () => ref('eval_suite', suiteId));
|
|
81
|
+
return mw(c, next);
|
|
82
|
+
});
|
|
83
|
+
r.use('/:suiteId', async (c, next) => {
|
|
84
|
+
if (c.req.method !== 'GET') return next();
|
|
85
|
+
const suiteId = c.req.param('suiteId') ?? '';
|
|
86
|
+
const mw = authorizer.authorize('read', () => ref('eval_suite', suiteId));
|
|
87
|
+
return mw(c, next);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------- GET / (list, cursor-paginated) ----------
|
|
92
|
+
r.get('/', async (c) => {
|
|
93
|
+
const requestId = c.get('requestId');
|
|
94
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
95
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
96
|
+
|
|
97
|
+
const cursorRaw = c.req.query('cursor');
|
|
98
|
+
const kindRaw = c.req.query('kind');
|
|
99
|
+
const nameRaw = c.req.query('name');
|
|
100
|
+
|
|
101
|
+
if (kindRaw !== undefined && kindRaw.length > 0 && !isEvalKind(kindRaw)) {
|
|
102
|
+
c.status(statusFor('bad-input') as never);
|
|
103
|
+
return c.json(
|
|
104
|
+
toWireError(
|
|
105
|
+
{
|
|
106
|
+
code: 'bad-input',
|
|
107
|
+
message: `Unknown eval kind "${kindRaw}". Expected one of: ${EVAL_KINDS.join(', ')}.`,
|
|
108
|
+
},
|
|
109
|
+
requestId,
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const scopeParsed = parseScopeParams(c.req.query(), { tenantId });
|
|
115
|
+
if (scopeParsed.kind === 'err') {
|
|
116
|
+
c.status(statusFor('scope-invalid') as never);
|
|
117
|
+
return c.json(
|
|
118
|
+
toWireError({ code: 'scope-invalid', message: scopeParsed.message }, requestId),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const page = await binding.list({
|
|
123
|
+
tenantId,
|
|
124
|
+
limit,
|
|
125
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
126
|
+
...(kindRaw !== undefined && kindRaw.length > 0 && { evalKind: kindRaw as EvalKind }),
|
|
127
|
+
...(nameRaw !== undefined && nameRaw.length > 0 && { nameFilter: nameRaw }),
|
|
128
|
+
...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
|
|
129
|
+
...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
|
|
130
|
+
});
|
|
131
|
+
return c.json({
|
|
132
|
+
data: page.data.map(serializeEvalSuite),
|
|
133
|
+
hasMore: page.nextCursor !== undefined,
|
|
134
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// ---------- GET /:suiteId (latest version) ----------
|
|
139
|
+
r.get('/:suiteId', async (c) => {
|
|
140
|
+
const requestId = c.get('requestId');
|
|
141
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
142
|
+
const suiteId = c.req.param('suiteId');
|
|
143
|
+
|
|
144
|
+
const suite = await binding.get({ tenantId, suiteId });
|
|
145
|
+
if (suite === null) {
|
|
146
|
+
// 410 gone (head exists, no active version) vs 404 not-found.
|
|
147
|
+
const exists = await binding.headExists({ tenantId, suiteId });
|
|
148
|
+
if (exists) {
|
|
149
|
+
c.status(statusFor('eval-suite-gone') as never);
|
|
150
|
+
return c.json(
|
|
151
|
+
toWireError(
|
|
152
|
+
{
|
|
153
|
+
code: 'eval-suite-gone',
|
|
154
|
+
message: `Eval suite "${suiteId}" has no active versions; reinstate a tombstoned version or publish a new one`,
|
|
155
|
+
suiteId,
|
|
156
|
+
},
|
|
157
|
+
requestId,
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
c.status(statusFor('eval-suite-not-found') as never);
|
|
162
|
+
return c.json(
|
|
163
|
+
toWireError(
|
|
164
|
+
{
|
|
165
|
+
code: 'eval-suite-not-found',
|
|
166
|
+
message: `No eval suite registered with id "${suiteId}"`,
|
|
167
|
+
suiteId,
|
|
168
|
+
},
|
|
169
|
+
requestId,
|
|
170
|
+
),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
return c.json(serializeEvalSuite(suite));
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ---------- GET /:suiteId/versions (list versions) ----------
|
|
177
|
+
r.get('/:suiteId/versions', async (c) => {
|
|
178
|
+
const requestId = c.get('requestId');
|
|
179
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
180
|
+
const suiteId = c.req.param('suiteId');
|
|
181
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
182
|
+
const cursorRaw = c.req.query('cursor');
|
|
183
|
+
|
|
184
|
+
// Confirm the id exists at all — an empty versions list from the
|
|
185
|
+
// binding is ambiguous (no versions vs. unknown id), so we do a
|
|
186
|
+
// preliminary `get` to flip an unknown id to a `404`.
|
|
187
|
+
const latest = await binding.get({ tenantId, suiteId });
|
|
188
|
+
if (latest === null) {
|
|
189
|
+
c.status(statusFor('eval-suite-not-found') as never);
|
|
190
|
+
return c.json(
|
|
191
|
+
toWireError(
|
|
192
|
+
{
|
|
193
|
+
code: 'eval-suite-not-found',
|
|
194
|
+
message: `No eval suite registered with id "${suiteId}"`,
|
|
195
|
+
suiteId,
|
|
196
|
+
},
|
|
197
|
+
requestId,
|
|
198
|
+
),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const page = await binding.listVersions({
|
|
203
|
+
tenantId,
|
|
204
|
+
suiteId,
|
|
205
|
+
limit,
|
|
206
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
207
|
+
});
|
|
208
|
+
return c.json({
|
|
209
|
+
data: page.data.map(serializeEvalSuite),
|
|
210
|
+
hasMore: page.nextCursor !== undefined,
|
|
211
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// ---------- GET /:suiteId/versions/:version ----------
|
|
216
|
+
r.get('/:suiteId/versions/:version', async (c) => {
|
|
217
|
+
const requestId = c.get('requestId');
|
|
218
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
219
|
+
const suiteId = c.req.param('suiteId');
|
|
220
|
+
const version = c.req.param('version');
|
|
221
|
+
|
|
222
|
+
const suite = await binding.getVersion({ tenantId, suiteId, version });
|
|
223
|
+
if (suite === null) {
|
|
224
|
+
c.status(statusFor('eval-suite-not-found') as never);
|
|
225
|
+
return c.json(
|
|
226
|
+
toWireError(
|
|
227
|
+
{
|
|
228
|
+
code: 'eval-suite-not-found',
|
|
229
|
+
message: `No eval suite "${suiteId}" at version "${version}"`,
|
|
230
|
+
suiteId,
|
|
231
|
+
version,
|
|
232
|
+
},
|
|
233
|
+
requestId,
|
|
234
|
+
),
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
return c.json(serializeEvalSuite(suite));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// ---------- POST / (publish) ----------
|
|
241
|
+
r.post('/', async (c) => {
|
|
242
|
+
const requestId = c.get('requestId');
|
|
243
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
244
|
+
|
|
245
|
+
let body: unknown;
|
|
246
|
+
try {
|
|
247
|
+
body = await c.req.json();
|
|
248
|
+
} catch {
|
|
249
|
+
c.status(statusFor('bad-input') as never);
|
|
250
|
+
return c.json(
|
|
251
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
if (body === null || typeof body !== 'object') {
|
|
255
|
+
c.status(statusFor('bad-input') as never);
|
|
256
|
+
return c.json(
|
|
257
|
+
toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// `projectId` is REQUIRED on the POST body.
|
|
262
|
+
// Missing / empty / non-string → 400 bad-input. Absent from the
|
|
263
|
+
// eval-suite-shape validator on purpose — the caller controls what
|
|
264
|
+
// project the suite lands in; the suite definition itself is
|
|
265
|
+
// project-agnostic.
|
|
266
|
+
const bodyObj = body as Record<string, unknown>;
|
|
267
|
+
const projectIdRaw = bodyObj.projectId;
|
|
268
|
+
if (typeof projectIdRaw !== 'string' || projectIdRaw.length === 0) {
|
|
269
|
+
c.status(statusFor('bad-input') as never);
|
|
270
|
+
return c.json(
|
|
271
|
+
toWireError({ code: 'bad-input', message: '`projectId` is required' }, requestId),
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
const projectId = projectIdRaw as ProjectId;
|
|
275
|
+
|
|
276
|
+
// Validate the wire shape. Deeper `spec` validation is the runtime
|
|
277
|
+
// consumer's responsibility (each eval kind has its own contract);
|
|
278
|
+
// the registry only guarantees the top-level shape. `projectId`
|
|
279
|
+
// is stripped before validation — the suite definition itself is
|
|
280
|
+
// project-agnostic.
|
|
281
|
+
const { projectId: _pid, ...bodyWithoutProjectId } = bodyObj;
|
|
282
|
+
const validation = validateEvalSuite(bodyWithoutProjectId, tenantId);
|
|
283
|
+
if (validation.kind === 'err') {
|
|
284
|
+
c.status(statusFor('validation-failed') as never);
|
|
285
|
+
return c.json(
|
|
286
|
+
toWireError(
|
|
287
|
+
{
|
|
288
|
+
code: 'validation-failed',
|
|
289
|
+
message: validation.error.message,
|
|
290
|
+
issues: validation.error.issues as unknown as Record<string, unknown>[],
|
|
291
|
+
},
|
|
292
|
+
requestId,
|
|
293
|
+
),
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const principal = c.get('principal') as Principal | undefined;
|
|
298
|
+
const creatorUserId =
|
|
299
|
+
principal?.actor.kind === 'user' ? (principal.actor.id as UserId) : undefined;
|
|
300
|
+
const outcome = await binding.publish({
|
|
301
|
+
tenantId,
|
|
302
|
+
projectId,
|
|
303
|
+
suite: validation.value,
|
|
304
|
+
enqueueTuples: (suiteId) =>
|
|
305
|
+
tuplesForCreate({ kind: 'eval_suite', id: suiteId, tenantId, projectId }, creatorUserId),
|
|
306
|
+
});
|
|
307
|
+
if (outcome.kind === 'already-registered') {
|
|
308
|
+
c.status(statusFor('eval-suite-already-registered') as never);
|
|
309
|
+
return c.json(
|
|
310
|
+
toWireError(
|
|
311
|
+
{
|
|
312
|
+
code: 'eval-suite-already-registered',
|
|
313
|
+
message: `Eval suite "${outcome.suiteId}" version "${outcome.version}" is already registered`,
|
|
314
|
+
suiteId: outcome.suiteId,
|
|
315
|
+
version: outcome.version,
|
|
316
|
+
},
|
|
317
|
+
requestId,
|
|
318
|
+
),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
if (outcome.kind === 'project-not-found') {
|
|
322
|
+
// Caller supplied a `projectId` that does not resolve within
|
|
323
|
+
// this tenant. Distinct signal from `already-registered` so the
|
|
324
|
+
// client can prompt for a valid project rather than assume the
|
|
325
|
+
// version was already used. Answered as `400 bad-input`; the
|
|
326
|
+
// caller learns from the message which field was invalid.
|
|
327
|
+
c.status(statusFor('bad-input') as never);
|
|
328
|
+
return c.json(
|
|
329
|
+
toWireError(
|
|
330
|
+
{
|
|
331
|
+
code: 'bad-input',
|
|
332
|
+
message: `\`projectId\` "${outcome.projectId as unknown as string}" does not resolve to a project in this tenant`,
|
|
333
|
+
},
|
|
334
|
+
requestId,
|
|
335
|
+
),
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
c.status(201);
|
|
339
|
+
return c.json({ suiteId: outcome.suiteId, version: outcome.version });
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// ---------- POST /:suiteId/versions/:version/unregister ----------
|
|
343
|
+
r.post('/:suiteId/versions/:version/unregister', async (c) => {
|
|
344
|
+
const requestId = c.get('requestId');
|
|
345
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
346
|
+
const suiteId = c.req.param('suiteId');
|
|
347
|
+
const version = c.req.param('version');
|
|
348
|
+
|
|
349
|
+
const outcome = await binding.unregister({ tenantId, suiteId, version });
|
|
350
|
+
if (!outcome.unregistered) {
|
|
351
|
+
c.status(statusFor('eval-suite-not-found') as never);
|
|
352
|
+
return c.json(
|
|
353
|
+
toWireError(
|
|
354
|
+
{
|
|
355
|
+
code: 'eval-suite-not-found',
|
|
356
|
+
message: `No eval suite "${suiteId}" at version "${version}" to unregister`,
|
|
357
|
+
suiteId,
|
|
358
|
+
version,
|
|
359
|
+
},
|
|
360
|
+
requestId,
|
|
361
|
+
),
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
return c.json({ suiteId, version, unregistered: true });
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// ---------- POST /:suiteId/versions/:version/reinstate ----------
|
|
368
|
+
r.post('/:suiteId/versions/:version/reinstate', async (c) => {
|
|
369
|
+
const requestId = c.get('requestId');
|
|
370
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
371
|
+
const suiteId = c.req.param('suiteId');
|
|
372
|
+
const version = c.req.param('version');
|
|
373
|
+
const outcome = await binding.reinstateVersion({ tenantId, suiteId, version });
|
|
374
|
+
if (outcome.kind === 'not-found') {
|
|
375
|
+
c.status(statusFor('eval-suite-not-found') as never);
|
|
376
|
+
return c.json(
|
|
377
|
+
toWireError(
|
|
378
|
+
{
|
|
379
|
+
code: 'eval-suite-not-found',
|
|
380
|
+
message: `No eval suite "${suiteId}" at version "${version}" to reinstate`,
|
|
381
|
+
suiteId,
|
|
382
|
+
version,
|
|
383
|
+
},
|
|
384
|
+
requestId,
|
|
385
|
+
),
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
return c.json({
|
|
389
|
+
suiteId: outcome.suiteId,
|
|
390
|
+
version: outcome.version,
|
|
391
|
+
wasTombstoned: outcome.wasTombstoned,
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return r;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function serializeEvalSuite(s: EvalSuite): Record<string, unknown> {
|
|
399
|
+
return {
|
|
400
|
+
id: s.id,
|
|
401
|
+
tenantId: s.tenantId as unknown as string,
|
|
402
|
+
version: s.version,
|
|
403
|
+
kind: s.kind,
|
|
404
|
+
...(s.description !== undefined && { description: s.description }),
|
|
405
|
+
spec: s.spec,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function isEvalKind(value: string): value is EvalKind {
|
|
410
|
+
return (EVAL_KINDS as readonly string[]).includes(value);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const SEMVER_RE = /^\d+\.\d+\.\d+$/;
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Wire-shape validator for `EvalSuite`. Confirms the top-level fields
|
|
417
|
+
* the registry needs (id, tenantId, semver version, kind ∈ closed enum,
|
|
418
|
+
* spec is an object). Deeper validation of `spec` is the runtime
|
|
419
|
+
* consumer's responsibility per eval kind.
|
|
420
|
+
*/
|
|
421
|
+
function validateEvalSuite(
|
|
422
|
+
body: unknown,
|
|
423
|
+
tenantId: TenantId,
|
|
424
|
+
):
|
|
425
|
+
| { kind: 'ok'; value: EvalSuite }
|
|
426
|
+
| {
|
|
427
|
+
kind: 'err';
|
|
428
|
+
error: { message: string; issues: readonly { path: string; message: string }[] };
|
|
429
|
+
} {
|
|
430
|
+
const b = body as Partial<EvalSuite> & Record<string, unknown>;
|
|
431
|
+
const issues: { path: string; message: string }[] = [];
|
|
432
|
+
|
|
433
|
+
if (typeof b.id !== 'string' || b.id.length === 0) {
|
|
434
|
+
issues.push({ path: 'id', message: 'evalSuite.id must be a non-empty string' });
|
|
435
|
+
}
|
|
436
|
+
if (typeof b.version !== 'string' || !SEMVER_RE.test(b.version)) {
|
|
437
|
+
issues.push({
|
|
438
|
+
path: 'version',
|
|
439
|
+
message: 'evalSuite.version must be a semver string (e.g. "1.0.0")',
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
if (typeof b.kind !== 'string' || !isEvalKind(b.kind)) {
|
|
443
|
+
issues.push({
|
|
444
|
+
path: 'kind',
|
|
445
|
+
message: `evalSuite.kind must be one of: ${EVAL_KINDS.join(', ')}`,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
// tenantId is optional on the wire — when present, it must match the
|
|
449
|
+
// caller's tenant (server-derived from the token). Cross-tenant
|
|
450
|
+
// publish is not allowed.
|
|
451
|
+
if (b.tenantId !== undefined) {
|
|
452
|
+
if (
|
|
453
|
+
typeof b.tenantId !== 'string' ||
|
|
454
|
+
(b.tenantId as unknown as string) !== (tenantId as unknown as string)
|
|
455
|
+
) {
|
|
456
|
+
issues.push({
|
|
457
|
+
path: 'tenantId',
|
|
458
|
+
message: 'evalSuite.tenantId must match the caller tenant',
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (
|
|
463
|
+
b.spec === undefined ||
|
|
464
|
+
b.spec === null ||
|
|
465
|
+
typeof b.spec !== 'object' ||
|
|
466
|
+
Array.isArray(b.spec)
|
|
467
|
+
) {
|
|
468
|
+
issues.push({ path: 'spec', message: 'evalSuite.spec must be an object' });
|
|
469
|
+
}
|
|
470
|
+
if (b.description !== undefined && typeof b.description !== 'string') {
|
|
471
|
+
issues.push({ path: 'description', message: 'evalSuite.description must be a string' });
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (issues.length > 0) {
|
|
475
|
+
return {
|
|
476
|
+
kind: 'err',
|
|
477
|
+
error: { message: issues[0]?.message ?? 'evalSuite validation failed', issues },
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const value: EvalSuite = {
|
|
482
|
+
id: b.id as string,
|
|
483
|
+
tenantId,
|
|
484
|
+
version: b.version as string,
|
|
485
|
+
kind: b.kind as EvalKind,
|
|
486
|
+
...(typeof b.description === 'string' && { description: b.description }),
|
|
487
|
+
spec: b.spec as Readonly<Record<string, unknown>>,
|
|
488
|
+
};
|
|
489
|
+
return { kind: 'ok', value };
|
|
490
|
+
}
|