@kindgi/api 0.0.0-bootstrap.0 → 0.1.0
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 +396 -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 +264 -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 +13 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -0
- package/dist/middleware/error-mapper.js +32 -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 +5051 -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 +773 -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 +29659 -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 +1285 -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 +291 -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 +37 -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 +5445 -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 +981 -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,104 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
import { ref } from '@kindgi/authz';
|
|
7
|
+
import type { RunBinding } from '@kindgi/runtime';
|
|
8
|
+
import type { RunId, TenantId } from '@kindgi/types';
|
|
9
|
+
|
|
10
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
11
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
12
|
+
import { MAX_PUBLIC_RUN_TOKEN_RUNS, type MintPublicRunTokenResult } from '../public-run-token.js';
|
|
13
|
+
import type { AppEnv } from '../types.js';
|
|
14
|
+
|
|
15
|
+
export interface PublicRunTokenIssuer {
|
|
16
|
+
readonly mint: (
|
|
17
|
+
tenantId: TenantId,
|
|
18
|
+
runIds: readonly RunId[],
|
|
19
|
+
ttlSeconds: number,
|
|
20
|
+
) => MintPublicRunTokenResult;
|
|
21
|
+
readonly defaultTtlSeconds: number;
|
|
22
|
+
readonly maxTtlSeconds: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const BODY_FIELDS = new Set(['runIds', 'expiresInSeconds']);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* `POST /v1/tokens/public`: mint a public run token for runs the caller
|
|
29
|
+
* may read. The token itself can't reach this route.
|
|
30
|
+
*/
|
|
31
|
+
export function publicRunTokensRouter(
|
|
32
|
+
runBinding: RunBinding,
|
|
33
|
+
issuer: PublicRunTokenIssuer,
|
|
34
|
+
authorizer?: Authorizer,
|
|
35
|
+
): Hono<AppEnv> {
|
|
36
|
+
const r = new Hono<AppEnv>();
|
|
37
|
+
|
|
38
|
+
r.post('/', async (c) => {
|
|
39
|
+
const requestId = c.get('requestId');
|
|
40
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
41
|
+
const error = (code: string, message: string, details: Record<string, unknown> = {}) => {
|
|
42
|
+
c.status(statusFor(code) as never);
|
|
43
|
+
return c.json(toWireError({ code, message, ...details }, requestId));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let body: unknown;
|
|
47
|
+
try {
|
|
48
|
+
body = await c.req.json();
|
|
49
|
+
} catch {
|
|
50
|
+
return error('bad-input', 'Request body must be valid JSON');
|
|
51
|
+
}
|
|
52
|
+
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
53
|
+
return error('bad-input', 'Request body must be a JSON object');
|
|
54
|
+
}
|
|
55
|
+
const fields = body as Record<string, unknown>;
|
|
56
|
+
const unknown = Object.keys(fields).find((key) => !BODY_FIELDS.has(key));
|
|
57
|
+
if (unknown !== undefined) return error('unknown-field', `Unknown field \`${unknown}\``);
|
|
58
|
+
|
|
59
|
+
const runIds = fields.runIds;
|
|
60
|
+
if (
|
|
61
|
+
!Array.isArray(runIds) ||
|
|
62
|
+
runIds.length === 0 ||
|
|
63
|
+
runIds.length > MAX_PUBLIC_RUN_TOKEN_RUNS ||
|
|
64
|
+
!runIds.every((id) => typeof id === 'string' && id.length > 0)
|
|
65
|
+
) {
|
|
66
|
+
return error(
|
|
67
|
+
'bad-input',
|
|
68
|
+
`\`runIds\` must be 1–${MAX_PUBLIC_RUN_TOKEN_RUNS} non-empty run ids`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const ttl = fields.expiresInSeconds ?? issuer.defaultTtlSeconds;
|
|
72
|
+
if (!Number.isInteger(ttl) || (ttl as number) < 1 || (ttl as number) > issuer.maxTtlSeconds) {
|
|
73
|
+
return error(
|
|
74
|
+
'bad-input',
|
|
75
|
+
`\`expiresInSeconds\` must be an integer in 1–${issuer.maxTtlSeconds}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const unique = [...new Set(runIds as string[])] as RunId[];
|
|
80
|
+
for (const runId of unique) {
|
|
81
|
+
const row = await runBinding.getRun(tenantId, runId);
|
|
82
|
+
if (row === null) {
|
|
83
|
+
return error('run-not-found', `No run with id ${runId}`, { runId });
|
|
84
|
+
}
|
|
85
|
+
if (
|
|
86
|
+
authorizer !== undefined &&
|
|
87
|
+
!(await authorizer.can(c, 'read', ref('project', row.projectId as unknown as string)))
|
|
88
|
+
) {
|
|
89
|
+
return error('permission-denied', `Not allowed to read run ${runId}`, { runId });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const minted = issuer.mint(tenantId, unique, ttl as number);
|
|
94
|
+
if (minted.kind === 'err') return error('token-mint-failed', minted.message);
|
|
95
|
+
c.status(201);
|
|
96
|
+
return c.json({
|
|
97
|
+
token: minted.token,
|
|
98
|
+
expiresAt: minted.expiresAt.toISOString(),
|
|
99
|
+
runIds: unique,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return r;
|
|
104
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
import { ref } from '@kindgi/authz';
|
|
7
|
+
import { RETENTION_DOMAINS, type RetentionDomain } from '@kindgi/policy-contract';
|
|
8
|
+
import type { TenantId } from '@kindgi/types';
|
|
9
|
+
|
|
10
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
11
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
12
|
+
import type { RetentionBinding } from '../retention-binding.js';
|
|
13
|
+
import type { AppEnv } from '../types.js';
|
|
14
|
+
import { clampLimit } from './pagination.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Retention resource routes — admin surface for the retention
|
|
18
|
+
* pipeline.
|
|
19
|
+
*
|
|
20
|
+
* - `GET /v1/retention/scheduled` tombstoned rows scheduled for deletion
|
|
21
|
+
* (`?pastGraceOnly=true`: only what a
|
|
22
|
+
* sweep would purge now)
|
|
23
|
+
* - `POST /v1/retention/sweep` "purge every past-grace tombstone in this tenant"
|
|
24
|
+
* - `POST /v1/retention/sweep/:domain` same but narrowed to one domain
|
|
25
|
+
*
|
|
26
|
+
* PEP: reads and writes both require `admin` on `tenant:<tenantId>`,
|
|
27
|
+
* matching how the other tenant-scoped admin knobs gate.
|
|
28
|
+
*/
|
|
29
|
+
export function retentionRouter(binding: RetentionBinding, authorizer?: Authorizer): Hono<AppEnv> {
|
|
30
|
+
const r = new Hono<AppEnv>();
|
|
31
|
+
|
|
32
|
+
// Every retention op is tenant-admin only.
|
|
33
|
+
if (authorizer !== undefined) {
|
|
34
|
+
r.use('/*', async (c, next) => {
|
|
35
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
36
|
+
const mw = authorizer.authorize('admin', async () =>
|
|
37
|
+
ref('tenant', tenantId as unknown as string),
|
|
38
|
+
);
|
|
39
|
+
return mw(c, next);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
r.get('/scheduled', async (c) => {
|
|
44
|
+
const requestId = c.get('requestId');
|
|
45
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
46
|
+
const url = new URL(c.req.url);
|
|
47
|
+
|
|
48
|
+
const domain = parseDomain(url.searchParams.get('domain'));
|
|
49
|
+
if (domain === 'invalid') {
|
|
50
|
+
c.status(statusFor('bad-input') as never);
|
|
51
|
+
return c.json(
|
|
52
|
+
toWireError(
|
|
53
|
+
{
|
|
54
|
+
code: 'bad-input',
|
|
55
|
+
message: `\`domain\` must be one of: ${RETENTION_DOMAINS.join(', ')}`,
|
|
56
|
+
},
|
|
57
|
+
requestId,
|
|
58
|
+
),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const limit = clampLimit(url.searchParams.get('limit') ?? undefined);
|
|
63
|
+
const pastGraceRaw = url.searchParams.get('pastGraceOnly');
|
|
64
|
+
const pastGraceOnly = pastGraceRaw === 'true';
|
|
65
|
+
|
|
66
|
+
const page = await binding.scheduled({
|
|
67
|
+
tenantId,
|
|
68
|
+
limit,
|
|
69
|
+
pastGraceOnly,
|
|
70
|
+
...(domain !== undefined && { domain }),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return c.json(page);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
r.post('/sweep', async (c) => {
|
|
77
|
+
const requestId = c.get('requestId');
|
|
78
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
79
|
+
|
|
80
|
+
let body: unknown = {};
|
|
81
|
+
try {
|
|
82
|
+
const raw = await c.req.text();
|
|
83
|
+
if (raw.length > 0) body = JSON.parse(raw);
|
|
84
|
+
} catch {
|
|
85
|
+
c.status(statusFor('bad-input') as never);
|
|
86
|
+
return c.json(
|
|
87
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
if (typeof body !== 'object' || body === null) {
|
|
91
|
+
c.status(statusFor('bad-input') as never);
|
|
92
|
+
return c.json(
|
|
93
|
+
toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const parsed = parseSweepBody(body as Record<string, unknown>);
|
|
97
|
+
if (parsed.kind === 'err') {
|
|
98
|
+
c.status(statusFor('bad-input') as never);
|
|
99
|
+
return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const result = await binding.sweep({
|
|
103
|
+
tenantId,
|
|
104
|
+
...(parsed.value.domain !== undefined && { domain: parsed.value.domain }),
|
|
105
|
+
...(parsed.value.maxPerDomain !== undefined && { maxPerDomain: parsed.value.maxPerDomain }),
|
|
106
|
+
});
|
|
107
|
+
return c.json(result);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
r.post('/sweep/:domain', async (c) => {
|
|
111
|
+
const requestId = c.get('requestId');
|
|
112
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
113
|
+
const domain = parseDomain(c.req.param('domain'));
|
|
114
|
+
if (domain === undefined || domain === 'invalid') {
|
|
115
|
+
c.status(statusFor('bad-input') as never);
|
|
116
|
+
return c.json(
|
|
117
|
+
toWireError(
|
|
118
|
+
{
|
|
119
|
+
code: 'bad-input',
|
|
120
|
+
message: `\`:domain\` must be one of: ${RETENTION_DOMAINS.filter((d) => d !== '*').join(', ')}`,
|
|
121
|
+
},
|
|
122
|
+
requestId,
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let body: unknown = {};
|
|
128
|
+
try {
|
|
129
|
+
const raw = await c.req.text();
|
|
130
|
+
if (raw.length > 0) body = JSON.parse(raw);
|
|
131
|
+
} catch {
|
|
132
|
+
c.status(statusFor('bad-input') as never);
|
|
133
|
+
return c.json(
|
|
134
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
if (typeof body !== 'object' || body === null) body = {};
|
|
138
|
+
|
|
139
|
+
const parsed = parseSweepBody(body as Record<string, unknown>);
|
|
140
|
+
if (parsed.kind === 'err') {
|
|
141
|
+
c.status(statusFor('bad-input') as never);
|
|
142
|
+
return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const result = await binding.sweep({
|
|
146
|
+
tenantId,
|
|
147
|
+
domain,
|
|
148
|
+
...(parsed.value.maxPerDomain !== undefined && { maxPerDomain: parsed.value.maxPerDomain }),
|
|
149
|
+
});
|
|
150
|
+
return c.json(result);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return r;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function parseDomain(raw: string | null | undefined): RetentionDomain | 'invalid' | undefined {
|
|
157
|
+
if (raw === null || raw === undefined || raw === '') return undefined;
|
|
158
|
+
if ((RETENTION_DOMAINS as readonly string[]).includes(raw)) return raw as RetentionDomain;
|
|
159
|
+
return 'invalid';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function parseSweepBody(body: Record<string, unknown>):
|
|
163
|
+
| {
|
|
164
|
+
readonly kind: 'ok';
|
|
165
|
+
readonly value: {
|
|
166
|
+
readonly domain?: RetentionDomain;
|
|
167
|
+
readonly maxPerDomain?: number;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
| { readonly kind: 'err'; readonly message: string } {
|
|
171
|
+
const value: { domain?: RetentionDomain; maxPerDomain?: number } = {};
|
|
172
|
+
if ('domain' in body) {
|
|
173
|
+
const parsed = parseDomain(String(body.domain));
|
|
174
|
+
if (parsed === 'invalid') {
|
|
175
|
+
return {
|
|
176
|
+
kind: 'err',
|
|
177
|
+
message: `\`domain\` must be one of: ${RETENTION_DOMAINS.join(', ')}`,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (parsed !== undefined) value.domain = parsed;
|
|
181
|
+
}
|
|
182
|
+
if ('maxPerDomain' in body) {
|
|
183
|
+
const n = body.maxPerDomain;
|
|
184
|
+
if (typeof n !== 'number' || !Number.isInteger(n) || n <= 0 || n > 10_000) {
|
|
185
|
+
return {
|
|
186
|
+
kind: 'err',
|
|
187
|
+
message: '`maxPerDomain` must be a positive integer ≤ 10000',
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
value.maxPerDomain = n;
|
|
191
|
+
}
|
|
192
|
+
return { kind: 'ok', value };
|
|
193
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
import type { ReviewerRole } from '@kindgi/authz';
|
|
7
|
+
import type { Cursor, ReviewerId, TenantId, UserId } from '@kindgi/types';
|
|
8
|
+
|
|
9
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
10
|
+
import type { ReviewerRecord, ReviewerRegistryBinding } from '../reviewer-binding.js';
|
|
11
|
+
import type { AppEnv } from '../types.js';
|
|
12
|
+
import { clampLimit } from './pagination.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Reviewer roster routes — sub-resource under
|
|
16
|
+
* `/v1/approvals/reviewers`. Roster management is caller-plugged via
|
|
17
|
+
* `ReviewerRegistryBinding`; the API package does NOT own persistence.
|
|
18
|
+
*
|
|
19
|
+
* The routes deliberately live OUTSIDE the reviewer-role gate applied
|
|
20
|
+
* inside `approvalsRouter`: registering a reviewer is an admin surface
|
|
21
|
+
* action, not a reviewer-only one, so requiring a `reviewerRole` on the
|
|
22
|
+
* caller would be circular ("only reviewers can appoint reviewers").
|
|
23
|
+
* The caller still needs a valid bearer token — the `/v1/*` auth chain
|
|
24
|
+
* covers that upstream.
|
|
25
|
+
*
|
|
26
|
+
* Mounted BEFORE `approvalsRouter` on the parent `/v1` router so path
|
|
27
|
+
* matching resolves `/v1/approvals/reviewers/*` here rather than being
|
|
28
|
+
* captured by the `/:approvalId` param inside the approvals router.
|
|
29
|
+
*/
|
|
30
|
+
const ROLE_VALUES: ReadonlySet<ReviewerRole> = new Set(['standard', 'senior', 'admin']);
|
|
31
|
+
|
|
32
|
+
export function reviewersRouter(binding: ReviewerRegistryBinding): Hono<AppEnv> {
|
|
33
|
+
const r = new Hono<AppEnv>();
|
|
34
|
+
|
|
35
|
+
// ---------- GET / (list, cursor-paginated) ----------
|
|
36
|
+
r.get('/', async (c) => {
|
|
37
|
+
const requestId = c.get('requestId');
|
|
38
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
39
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
40
|
+
|
|
41
|
+
const cursorRaw = c.req.query('cursor');
|
|
42
|
+
const roleRaw = c.req.query('role');
|
|
43
|
+
|
|
44
|
+
let roleFilter: ReviewerRole | undefined;
|
|
45
|
+
if (roleRaw !== undefined && roleRaw.length > 0) {
|
|
46
|
+
if (!ROLE_VALUES.has(roleRaw as ReviewerRole)) {
|
|
47
|
+
c.status(statusFor('bad-input') as never);
|
|
48
|
+
return c.json(
|
|
49
|
+
toWireError(
|
|
50
|
+
{ code: 'bad-input', message: `Unknown \`role\` value: ${roleRaw}` },
|
|
51
|
+
requestId,
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
roleFilter = roleRaw as ReviewerRole;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const page = await binding.list({
|
|
59
|
+
tenantId,
|
|
60
|
+
limit,
|
|
61
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
62
|
+
...(roleFilter !== undefined && { role: roleFilter }),
|
|
63
|
+
});
|
|
64
|
+
return c.json({
|
|
65
|
+
data: page.data.map(serializeReviewer),
|
|
66
|
+
hasMore: page.nextCursor !== undefined,
|
|
67
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// ---------- GET /:reviewerId ----------
|
|
72
|
+
r.get('/:reviewerId', async (c) => {
|
|
73
|
+
const requestId = c.get('requestId');
|
|
74
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
75
|
+
const reviewerId = c.req.param('reviewerId') as ReviewerId;
|
|
76
|
+
|
|
77
|
+
const reviewer = await binding.get({ tenantId, reviewerId });
|
|
78
|
+
if (reviewer === null) {
|
|
79
|
+
c.status(statusFor('reviewer-not-found') as never);
|
|
80
|
+
return c.json(
|
|
81
|
+
toWireError(
|
|
82
|
+
{
|
|
83
|
+
code: 'reviewer-not-found',
|
|
84
|
+
message: `No reviewer registered with id "${reviewerId as unknown as string}"`,
|
|
85
|
+
reviewerId: reviewerId as unknown as string,
|
|
86
|
+
},
|
|
87
|
+
requestId,
|
|
88
|
+
),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return c.json(serializeReviewer(reviewer));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ---------- POST / (register) ----------
|
|
95
|
+
r.post('/', async (c) => {
|
|
96
|
+
const requestId = c.get('requestId');
|
|
97
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
98
|
+
|
|
99
|
+
let body: unknown;
|
|
100
|
+
try {
|
|
101
|
+
body = await c.req.json();
|
|
102
|
+
} catch {
|
|
103
|
+
c.status(statusFor('bad-input') as never);
|
|
104
|
+
return c.json(
|
|
105
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const parsed = parseRegisterBody(body);
|
|
109
|
+
if (parsed.kind === 'err') {
|
|
110
|
+
c.status(statusFor('bad-input') as never);
|
|
111
|
+
return c.json(toWireError({ code: 'bad-input', message: parsed.message }, requestId));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const outcome = await binding.register({
|
|
115
|
+
tenantId,
|
|
116
|
+
userId: parsed.value.userId,
|
|
117
|
+
role: parsed.value.role,
|
|
118
|
+
...(parsed.value.displayName !== undefined && { displayName: parsed.value.displayName }),
|
|
119
|
+
});
|
|
120
|
+
c.status(201);
|
|
121
|
+
return c.json(serializeReviewer(outcome.reviewer));
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ---------- POST /:reviewerId/unregister ----------
|
|
125
|
+
r.post('/:reviewerId/unregister', async (c) => {
|
|
126
|
+
const requestId = c.get('requestId');
|
|
127
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
128
|
+
const reviewerId = c.req.param('reviewerId') as ReviewerId;
|
|
129
|
+
|
|
130
|
+
const outcome = await binding.unregister({ tenantId, reviewerId });
|
|
131
|
+
if (!outcome.unregistered) {
|
|
132
|
+
c.status(statusFor('reviewer-not-found') as never);
|
|
133
|
+
return c.json(
|
|
134
|
+
toWireError(
|
|
135
|
+
{
|
|
136
|
+
code: 'reviewer-not-found',
|
|
137
|
+
message: `No reviewer "${reviewerId as unknown as string}" to unregister`,
|
|
138
|
+
reviewerId: reviewerId as unknown as string,
|
|
139
|
+
},
|
|
140
|
+
requestId,
|
|
141
|
+
),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
return c.json({
|
|
145
|
+
reviewerId: reviewerId as unknown as string,
|
|
146
|
+
unregistered: true,
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return r;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function serializeReviewer(r: ReviewerRecord): Record<string, unknown> {
|
|
154
|
+
return {
|
|
155
|
+
id: r.id as unknown as string,
|
|
156
|
+
tenantId: r.tenantId as unknown as string,
|
|
157
|
+
userId: r.userId as unknown as string,
|
|
158
|
+
role: r.role,
|
|
159
|
+
...(r.displayName !== undefined && { displayName: r.displayName }),
|
|
160
|
+
createdAt: r.createdAt as unknown as string,
|
|
161
|
+
...(r.deactivatedAt !== undefined && {
|
|
162
|
+
deactivatedAt: r.deactivatedAt as unknown as string,
|
|
163
|
+
}),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
type ParsedRegister = {
|
|
168
|
+
readonly userId: UserId;
|
|
169
|
+
readonly role: ReviewerRole;
|
|
170
|
+
readonly displayName?: string;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
function parseRegisterBody(
|
|
174
|
+
body: unknown,
|
|
175
|
+
):
|
|
176
|
+
| { readonly kind: 'ok'; readonly value: ParsedRegister }
|
|
177
|
+
| { readonly kind: 'err'; readonly message: string } {
|
|
178
|
+
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
179
|
+
return { kind: 'err', message: 'Request body must be an object' };
|
|
180
|
+
}
|
|
181
|
+
const b = body as Record<string, unknown>;
|
|
182
|
+
const userId = b.userId;
|
|
183
|
+
if (typeof userId !== 'string' || userId.length === 0) {
|
|
184
|
+
return { kind: 'err', message: 'Field `userId` must be a non-empty string' };
|
|
185
|
+
}
|
|
186
|
+
const role = b.role;
|
|
187
|
+
if (typeof role !== 'string' || !ROLE_VALUES.has(role as ReviewerRole)) {
|
|
188
|
+
return { kind: 'err', message: 'Field `role` must be one of: standard, senior, admin' };
|
|
189
|
+
}
|
|
190
|
+
const displayNameRaw = b.displayName;
|
|
191
|
+
let displayName: string | undefined;
|
|
192
|
+
if (displayNameRaw !== undefined) {
|
|
193
|
+
if (typeof displayNameRaw !== 'string' || displayNameRaw.length === 0) {
|
|
194
|
+
return {
|
|
195
|
+
kind: 'err',
|
|
196
|
+
message: 'Field `displayName` must be a non-empty string when present',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
displayName = displayNameRaw;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
kind: 'ok',
|
|
203
|
+
value: {
|
|
204
|
+
userId: userId as UserId,
|
|
205
|
+
role: role as ReviewerRole,
|
|
206
|
+
...(displayName !== undefined && { displayName }),
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|