@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,437 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type { Context, MiddlewareHandler, Next } from 'hono';
|
|
5
|
+
|
|
6
|
+
import type { ReviewerRole } from '@kindgi/authz';
|
|
7
|
+
import type { ApiTokenId, SessionId, TenantId, UserId } from '@kindgi/types';
|
|
8
|
+
|
|
9
|
+
import type { SigningKeyBinding } from '@kindgi/crypto';
|
|
10
|
+
|
|
11
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
12
|
+
import { PUBLIC_RUN_TOKEN_PREFIX, verifyPublicRunToken } from '../public-run-token.js';
|
|
13
|
+
import type { SessionStoreBinding } from '../session-store-binding.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolve an API token → tenant identity. For static bearer tokens this
|
|
17
|
+
* is a caller-injected function: the platform's actual token store (auth
|
|
18
|
+
* service, database, …) plugs in. Signature stays stable across
|
|
19
|
+
* implementations.
|
|
20
|
+
*
|
|
21
|
+
* Return `null` for missing / expired / revoked tokens; the middleware
|
|
22
|
+
* translates to 401 with a specific error code.
|
|
23
|
+
*/
|
|
24
|
+
export type TokenResolver = (token: string) => Promise<TokenResolution | null>;
|
|
25
|
+
|
|
26
|
+
export interface TokenResolution {
|
|
27
|
+
readonly tenantId: TenantId;
|
|
28
|
+
/**
|
|
29
|
+
* Optional expiration; if set and in the past, the middleware treats
|
|
30
|
+
* as expired even if the resolver returned a value.
|
|
31
|
+
*/
|
|
32
|
+
readonly expiresAt?: Date;
|
|
33
|
+
/** Optional revocation marker; `true` → 401 auth-revoked. */
|
|
34
|
+
readonly revoked?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Optional reviewer role granted to this token. When present, the
|
|
37
|
+
* middleware surfaces it as `c.get('reviewerRole')` and approvals
|
|
38
|
+
* routes gate visibility / decisions on the `standard < senior < admin`
|
|
39
|
+
* hierarchy. Absent for tokens that were never provisioned with a
|
|
40
|
+
* reviewer role — such tokens can still hit `/v1/runs` etc., but any
|
|
41
|
+
* approvals route returns `403 permission-denied`.
|
|
42
|
+
*/
|
|
43
|
+
readonly reviewerRole?: ReviewerRole;
|
|
44
|
+
/**
|
|
45
|
+
* Optional user identity behind the token. Approvals routes forward
|
|
46
|
+
* this to a `ReviewerBinding` to translate `UserId → ReviewerId`
|
|
47
|
+
* before calling `hitl.submitReview` (which needs the reviewer id).
|
|
48
|
+
*/
|
|
49
|
+
readonly userId?: UserId;
|
|
50
|
+
/**
|
|
51
|
+
* The id of a durable API key (`POST /v1/tokens`). The caller is then
|
|
52
|
+
* the key's service account (`service_account:<tokenId>`), not a user;
|
|
53
|
+
* the middleware surfaces it as `c.get('tokenId')`.
|
|
54
|
+
*/
|
|
55
|
+
readonly tokenId?: ApiTokenId;
|
|
56
|
+
/**
|
|
57
|
+
* Optional session id. Populated by the session-token verifier path
|
|
58
|
+
* (`kgi_sk_*` tokens) so `/v1/identity/whoami` and `/v1/auth/logout`
|
|
59
|
+
* can introspect / revoke the caller's own session without a second
|
|
60
|
+
* lookup. Absent for static bearer tokens.
|
|
61
|
+
*/
|
|
62
|
+
readonly sessionId?: SessionId;
|
|
63
|
+
/**
|
|
64
|
+
* Optional identity-provider id that authenticated the caller. Only
|
|
65
|
+
* populated by session-token verification.
|
|
66
|
+
*/
|
|
67
|
+
readonly providerId?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Optional OAuth scopes granted to the session. Only populated by
|
|
70
|
+
* session-token verification.
|
|
71
|
+
*/
|
|
72
|
+
readonly scopes?: readonly string[];
|
|
73
|
+
/**
|
|
74
|
+
* Optional last-observed-activity timestamp. Populated by
|
|
75
|
+
* `resolveSessionToken` when the session-store adapter carries
|
|
76
|
+
* `lastActiveAt` on the row. Used by the middleware to enforce the
|
|
77
|
+
* `inactivityTimeoutMs` policy. Absent → inactivity check is
|
|
78
|
+
* skipped.
|
|
79
|
+
*/
|
|
80
|
+
readonly lastActiveAt?: Date;
|
|
81
|
+
/**
|
|
82
|
+
* Optional flag set by `resolveSessionToken` when the session was
|
|
83
|
+
* revoked specifically via rotation (`POST /v1/auth/refresh`). The
|
|
84
|
+
* middleware maps this to `401 refresh-token-invalid` instead of
|
|
85
|
+
* the generic `401 auth-revoked`, matching OAuth 2.1 BCP refresh-
|
|
86
|
+
* token-reuse semantics.
|
|
87
|
+
*/
|
|
88
|
+
readonly rotated?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Optional framework capabilities granted to the bearer. Route
|
|
91
|
+
* handlers gate write / reveal ops on
|
|
92
|
+
* specific capability strings (`env:write`, `secrets:write`,
|
|
93
|
+
* `secrets:rotate`, `secrets:revoke`, `secrets:revoke:hard`,
|
|
94
|
+
* `secrets:reveal`, `kindgi:system`). Callers that plug their
|
|
95
|
+
* own resolver populate this list from their token store; deployments
|
|
96
|
+
* without capability data leave it absent — routes that require a
|
|
97
|
+
* capability then return 403 `permission-denied`.
|
|
98
|
+
*
|
|
99
|
+
* Kindgi's stance: fail-closed on writes when the capability is
|
|
100
|
+
* unset (a token without an explicit `secrets:write` claim cannot
|
|
101
|
+
* mutate the secrets store). Deployments that want any authenticated
|
|
102
|
+
* bearer to be able to write grant the capability on every token.
|
|
103
|
+
*/
|
|
104
|
+
readonly capabilities?: readonly string[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Session-token prefix. Framework-issued opaque tokens minted by
|
|
109
|
+
* `POST /v1/auth/callback/:providerId` carry this prefix so the auth
|
|
110
|
+
* middleware can route them to the session store instead of the caller-
|
|
111
|
+
* plugged `TokenResolver`. Distinct prefix means a static bearer token
|
|
112
|
+
* and a session token can coexist byte-shape-identical on the wire.
|
|
113
|
+
*/
|
|
114
|
+
export const SESSION_TOKEN_PREFIX = 'kgi_sk_' as const;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Compose the on-wire session token from a `SessionId`. Session tokens
|
|
118
|
+
* are opaque to clients — the shape below is a framework convention,
|
|
119
|
+
* not part of the wire contract. Do NOT parse it in downstream code
|
|
120
|
+
* outside the middleware.
|
|
121
|
+
*/
|
|
122
|
+
export function encodeSessionToken(sessionId: SessionId): string {
|
|
123
|
+
return `${SESSION_TOKEN_PREFIX}${sessionId as unknown as string}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Optional wiring for the session-token flavor. Provided to the
|
|
128
|
+
* middleware via `bearerAuthMiddleware(resolveToken, { sessionStore })`
|
|
129
|
+
* when the deployment mounts `SessionStoreBinding`. Absent → session-
|
|
130
|
+
* shape tokens fall through to `TokenResolver` (which will typically
|
|
131
|
+
* `null` them → 401 auth-missing) so a deployment without a session
|
|
132
|
+
* store still behaves consistently.
|
|
133
|
+
*/
|
|
134
|
+
export interface BearerAuthMiddlewareOptions {
|
|
135
|
+
readonly sessionStore?: SessionStoreBinding;
|
|
136
|
+
/**
|
|
137
|
+
* Inactivity timeout — sessions whose `lastActiveAt` is older than
|
|
138
|
+
* `Date.now() - inactivityTimeoutMs` are rejected with 401
|
|
139
|
+
* `session-inactive`. Absent → inactivity enforcement disabled
|
|
140
|
+
* (only absolute TTL applies).
|
|
141
|
+
*
|
|
142
|
+
* Sensible default: 4 hours (`4 * 60 * 60 * 1000`). Deployments
|
|
143
|
+
* customize via `CreateAppInput.session.inactivityTimeout`.
|
|
144
|
+
*/
|
|
145
|
+
readonly inactivityTimeoutMs?: number;
|
|
146
|
+
/**
|
|
147
|
+
* How often (per session) the middleware should call
|
|
148
|
+
* `sessionStore.touch` to bump `lastActiveAt`. Higher throttle ⇒
|
|
149
|
+
* fewer writes but coarser inactivity enforcement. Defaults to 60s.
|
|
150
|
+
*/
|
|
151
|
+
readonly touchThrottleMs?: number;
|
|
152
|
+
/**
|
|
153
|
+
* Accept public run tokens (`kgi_pt_…`), verified against
|
|
154
|
+
* `signingKey`, on the routes `isAllowed` admits (every other route
|
|
155
|
+
* answers 403). Absent → such tokens are not recognized (401).
|
|
156
|
+
*/
|
|
157
|
+
readonly publicRunTokens?: {
|
|
158
|
+
readonly signingKey: SigningKeyBinding;
|
|
159
|
+
readonly isAllowed: (method: string, path: string) => boolean;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const DEFAULT_TOUCH_THROTTLE_MS = 60_000;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Bearer-token middleware. Fails 401 on missing / malformed / expired /
|
|
167
|
+
* revoked. On success, sets `c.set('tenantId', tenantId)` for downstream
|
|
168
|
+
* handlers.
|
|
169
|
+
*
|
|
170
|
+
* Two token flavors are accepted:
|
|
171
|
+
* - `kgi_sk_<sessionId>` — framework-issued OAuth session tokens.
|
|
172
|
+
* Verified via `sessionStore.get`; expiration + revocation are pulled
|
|
173
|
+
* from the session row.
|
|
174
|
+
* - anything else — caller-plugged static bearer tokens. Verified via
|
|
175
|
+
* `resolveToken`. Byte-shape-identical with the session-less contract.
|
|
176
|
+
*/
|
|
177
|
+
export function bearerAuthMiddleware(
|
|
178
|
+
resolve: TokenResolver,
|
|
179
|
+
options: BearerAuthMiddlewareOptions = {},
|
|
180
|
+
): MiddlewareHandler {
|
|
181
|
+
const { sessionStore, inactivityTimeoutMs } = options;
|
|
182
|
+
const touchThrottleMs = options.touchThrottleMs ?? DEFAULT_TOUCH_THROTTLE_MS;
|
|
183
|
+
// Per-process throttle bucket: session id → last touch millis.
|
|
184
|
+
// A shared Map is fine — session ids are opaque strings and the
|
|
185
|
+
// bucket is bounded by the number of active sessions the process
|
|
186
|
+
// has recently observed.
|
|
187
|
+
const touchBucket = new Map<string, number>();
|
|
188
|
+
return async (c, next) => {
|
|
189
|
+
const requestId = c.get('requestId') as string;
|
|
190
|
+
const header = c.req.header('authorization');
|
|
191
|
+
if (header === undefined || header.length === 0) {
|
|
192
|
+
const body = toWireError(
|
|
193
|
+
{ code: 'auth-missing', message: 'Authorization header is required' },
|
|
194
|
+
requestId,
|
|
195
|
+
);
|
|
196
|
+
return c.json(body, statusFor('auth-missing') as never);
|
|
197
|
+
}
|
|
198
|
+
const match = /^Bearer\s+(.+)$/i.exec(header);
|
|
199
|
+
if (match === null) {
|
|
200
|
+
const body = toWireError(
|
|
201
|
+
{
|
|
202
|
+
code: 'auth-missing',
|
|
203
|
+
message: 'Authorization header must be "Bearer <token>"',
|
|
204
|
+
},
|
|
205
|
+
requestId,
|
|
206
|
+
);
|
|
207
|
+
return c.json(body, statusFor('auth-missing') as never);
|
|
208
|
+
}
|
|
209
|
+
const token = match[1]?.trim() ?? '';
|
|
210
|
+
if (token.length === 0) {
|
|
211
|
+
const body = toWireError(
|
|
212
|
+
{ code: 'auth-missing', message: 'Bearer token is empty' },
|
|
213
|
+
requestId,
|
|
214
|
+
);
|
|
215
|
+
return c.json(body, statusFor('auth-missing') as never);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (token.startsWith(PUBLIC_RUN_TOKEN_PREFIX)) {
|
|
219
|
+
return authenticatePublicRunToken(c, next, token, requestId, options.publicRunTokens);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const isSessionToken = sessionStore !== undefined && token.startsWith(SESSION_TOKEN_PREFIX);
|
|
223
|
+
const resolution = isSessionToken
|
|
224
|
+
? await resolveSessionToken(sessionStore!, token)
|
|
225
|
+
: await resolve(token);
|
|
226
|
+
if (resolution === null) {
|
|
227
|
+
const body = toWireError(
|
|
228
|
+
{ code: 'auth-missing', message: 'Bearer token is not recognized' },
|
|
229
|
+
requestId,
|
|
230
|
+
);
|
|
231
|
+
return c.json(body, statusFor('auth-missing') as never);
|
|
232
|
+
}
|
|
233
|
+
if (resolution.revoked === true) {
|
|
234
|
+
// Rotated sessions surface as `refresh-token-invalid` — OAuth 2.1
|
|
235
|
+
// BCP reuse detection. The old session token is no longer valid,
|
|
236
|
+
// but the semantic distinction from an explicit revoke matters
|
|
237
|
+
// to compliant clients (they retry with the fresh token instead
|
|
238
|
+
// of prompting the user to re-authenticate).
|
|
239
|
+
if (resolution.rotated === true) {
|
|
240
|
+
const body = toWireError(
|
|
241
|
+
{
|
|
242
|
+
code: 'refresh-token-invalid',
|
|
243
|
+
message: 'Session token was rotated — retry with the fresh token from the last refresh',
|
|
244
|
+
},
|
|
245
|
+
requestId,
|
|
246
|
+
);
|
|
247
|
+
return c.json(body, statusFor('refresh-token-invalid') as never);
|
|
248
|
+
}
|
|
249
|
+
const body = toWireError(
|
|
250
|
+
{ code: 'auth-revoked', message: 'Bearer token has been revoked' },
|
|
251
|
+
requestId,
|
|
252
|
+
);
|
|
253
|
+
return c.json(body, statusFor('auth-revoked') as never);
|
|
254
|
+
}
|
|
255
|
+
if (resolution.expiresAt !== undefined && resolution.expiresAt.getTime() < Date.now()) {
|
|
256
|
+
// Session tokens report `session-expired` so callers can
|
|
257
|
+
// distinguish absolute session TTL from bearer-token expiry.
|
|
258
|
+
const expiredCode = isSessionToken ? 'session-expired' : 'auth-expired';
|
|
259
|
+
const expiredMsg = isSessionToken
|
|
260
|
+
? 'Session has expired (absolute TTL reached)'
|
|
261
|
+
: 'Bearer token has expired';
|
|
262
|
+
const body = toWireError({ code: expiredCode, message: expiredMsg }, requestId);
|
|
263
|
+
return c.json(body, statusFor(expiredCode) as never);
|
|
264
|
+
}
|
|
265
|
+
// Inactivity timeout enforcement. Only applies when the deployment
|
|
266
|
+
// opted in via `inactivityTimeoutMs` AND the token is a session
|
|
267
|
+
// token AND the store populated `lastActiveAt`. Skipping the check
|
|
268
|
+
// preserves the default contract for deployments that don't wire
|
|
269
|
+
// the config.
|
|
270
|
+
if (
|
|
271
|
+
isSessionToken &&
|
|
272
|
+
inactivityTimeoutMs !== undefined &&
|
|
273
|
+
inactivityTimeoutMs > 0 &&
|
|
274
|
+
resolution.lastActiveAt !== undefined
|
|
275
|
+
) {
|
|
276
|
+
const cutoff = Date.now() - inactivityTimeoutMs;
|
|
277
|
+
if (resolution.lastActiveAt.getTime() < cutoff) {
|
|
278
|
+
const body = toWireError(
|
|
279
|
+
{
|
|
280
|
+
code: 'session-inactive',
|
|
281
|
+
message: 'Session has been idle beyond the inactivity timeout',
|
|
282
|
+
},
|
|
283
|
+
requestId,
|
|
284
|
+
);
|
|
285
|
+
return c.json(body, statusFor('session-inactive') as never);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
c.set('tenantId', resolution.tenantId);
|
|
290
|
+
if (resolution.reviewerRole !== undefined) {
|
|
291
|
+
c.set('reviewerRole', resolution.reviewerRole);
|
|
292
|
+
}
|
|
293
|
+
if (resolution.userId !== undefined) {
|
|
294
|
+
c.set('userId', resolution.userId);
|
|
295
|
+
}
|
|
296
|
+
if (resolution.tokenId !== undefined) {
|
|
297
|
+
c.set('tokenId', resolution.tokenId);
|
|
298
|
+
}
|
|
299
|
+
if (resolution.sessionId !== undefined) {
|
|
300
|
+
c.set('sessionId', resolution.sessionId);
|
|
301
|
+
}
|
|
302
|
+
if (resolution.providerId !== undefined) {
|
|
303
|
+
c.set('providerId', resolution.providerId);
|
|
304
|
+
}
|
|
305
|
+
if (resolution.scopes !== undefined) {
|
|
306
|
+
c.set('scopes', resolution.scopes);
|
|
307
|
+
}
|
|
308
|
+
if (resolution.capabilities !== undefined) {
|
|
309
|
+
c.set('capabilities', resolution.capabilities);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Bump `lastActiveAt` (throttled) so the inactivity timeout has
|
|
313
|
+
// a fresh signal to compare against. Only meaningful for session
|
|
314
|
+
// tokens with a wired `touch()`; bearer tokens are skipped.
|
|
315
|
+
if (isSessionToken && sessionStore?.touch !== undefined && resolution.sessionId !== undefined) {
|
|
316
|
+
const sid = resolution.sessionId as unknown as string;
|
|
317
|
+
const last = touchBucket.get(sid) ?? 0;
|
|
318
|
+
const now = Date.now();
|
|
319
|
+
if (now - last >= touchThrottleMs) {
|
|
320
|
+
touchBucket.set(sid, now);
|
|
321
|
+
// Fire-and-forget; we don't want the write path to hold the
|
|
322
|
+
// request. Adapter errors surface via observability, not the
|
|
323
|
+
// hot path (the next check catches a genuinely stale row).
|
|
324
|
+
void sessionStore
|
|
325
|
+
.touch({
|
|
326
|
+
tenantId: resolution.tenantId,
|
|
327
|
+
sessionId: resolution.sessionId,
|
|
328
|
+
at: new Date(now),
|
|
329
|
+
})
|
|
330
|
+
.catch(() => {
|
|
331
|
+
// Best-effort — the next request retries.
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
await next();
|
|
337
|
+
return;
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Session-token verification path. Distinct from `TokenResolver` because
|
|
343
|
+
* a session carries structured OAuth context (userId + providerId +
|
|
344
|
+
* scopes + expiration + revocation) that the store returns natively —
|
|
345
|
+
* we don't want to squeeze that shape through the resolver contract.
|
|
346
|
+
*
|
|
347
|
+
* Session-token tenant scoping: the stored session is the source of
|
|
348
|
+
* truth for `tenantId`. We look up ACROSS tenants here — the resolved
|
|
349
|
+
* `tenantId` is whatever the session was written under, so everything
|
|
350
|
+
* downstream is scoped to that tenant only. A stolen session token still
|
|
351
|
+
* can't cross tenants because the session it points to belongs to
|
|
352
|
+
* exactly one tenant.
|
|
353
|
+
*
|
|
354
|
+
* Since `SessionStoreBinding.get` requires `tenantId`, the lookup is:
|
|
355
|
+
* extract `sessionId` from the token, then call
|
|
356
|
+
* `sessionStore.get({ tenantId: MULTI_TENANT_LOOKUP, sessionId })`.
|
|
357
|
+
* Session-store implementations MUST recognize the `MULTI_TENANT_LOOKUP`
|
|
358
|
+
* sentinel and skip the tenant filter; the `tenantId` on the stored
|
|
359
|
+
* session is authoritative.
|
|
360
|
+
*/
|
|
361
|
+
async function resolveSessionToken(
|
|
362
|
+
sessionStore: SessionStoreBinding,
|
|
363
|
+
token: string,
|
|
364
|
+
): Promise<TokenResolution | null> {
|
|
365
|
+
const sessionIdStr = token.slice(SESSION_TOKEN_PREFIX.length);
|
|
366
|
+
if (sessionIdStr.length === 0) return null;
|
|
367
|
+
const sessionId = sessionIdStr as unknown as SessionId;
|
|
368
|
+
const session = await sessionStore.get({
|
|
369
|
+
tenantId: MULTI_TENANT_LOOKUP,
|
|
370
|
+
sessionId,
|
|
371
|
+
});
|
|
372
|
+
if (session === null) return null;
|
|
373
|
+
return {
|
|
374
|
+
tenantId: session.tenantId,
|
|
375
|
+
userId: session.userId as unknown as UserId,
|
|
376
|
+
sessionId: session.id,
|
|
377
|
+
providerId: session.providerId,
|
|
378
|
+
scopes: session.scopes,
|
|
379
|
+
expiresAt: new Date(session.expiresAt as unknown as string),
|
|
380
|
+
revoked: session.revokedAt !== undefined,
|
|
381
|
+
...(session.rotatedAt !== undefined && { rotated: true }),
|
|
382
|
+
...(session.lastActiveAt !== undefined && {
|
|
383
|
+
lastActiveAt: new Date(session.lastActiveAt as unknown as string),
|
|
384
|
+
}),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Sentinel `tenantId` value the middleware passes to
|
|
390
|
+
* `SessionStoreBinding.get` when it needs to look up a session by its
|
|
391
|
+
* id without knowing the tenant in advance. Session-store adapters
|
|
392
|
+
* MUST honor this by skipping the tenant filter — the tenant is not
|
|
393
|
+
* known until the session row has been read.
|
|
394
|
+
*/
|
|
395
|
+
export const MULTI_TENANT_LOOKUP = '__kindgi_session_multi_tenant_lookup__' as unknown as TenantId;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* A public run token: verify it, admit only the routes it may use, and
|
|
399
|
+
* mark the request so the progress routes check it against the runs
|
|
400
|
+
* it names.
|
|
401
|
+
*/
|
|
402
|
+
async function authenticatePublicRunToken(
|
|
403
|
+
c: Context,
|
|
404
|
+
next: Next,
|
|
405
|
+
token: string,
|
|
406
|
+
requestId: string,
|
|
407
|
+
config: BearerAuthMiddlewareOptions['publicRunTokens'],
|
|
408
|
+
): Promise<Response | undefined> {
|
|
409
|
+
const verified =
|
|
410
|
+
config === undefined
|
|
411
|
+
? ({ kind: 'err', reason: 'unknown-key' } as const)
|
|
412
|
+
: verifyPublicRunToken(token, { signingKey: config.signingKey });
|
|
413
|
+
if (verified.kind === 'err') {
|
|
414
|
+
const expired = verified.reason === 'expired';
|
|
415
|
+
const code = expired ? 'auth-expired' : 'auth-missing';
|
|
416
|
+
const message = expired ? 'Public run token has expired' : 'Bearer token is not recognized';
|
|
417
|
+
return c.json(toWireError({ code, message }, requestId), statusFor(code) as never);
|
|
418
|
+
}
|
|
419
|
+
if (config === undefined || !config.isAllowed(c.req.method, c.req.path)) {
|
|
420
|
+
return c.json(
|
|
421
|
+
toWireError(
|
|
422
|
+
{
|
|
423
|
+
code: 'permission-denied',
|
|
424
|
+
message:
|
|
425
|
+
'A public run token can only follow the runs it names: GET /v1/runs/{runId}/progress and GET /v1/runs/{runId}/progress/stream',
|
|
426
|
+
},
|
|
427
|
+
requestId,
|
|
428
|
+
),
|
|
429
|
+
statusFor('permission-denied') as never,
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
c.set('tenantId', verified.claims.tenantId);
|
|
433
|
+
c.set('tokenKind', 'public-run');
|
|
434
|
+
c.set('publicRunIds', verified.claims.runIds);
|
|
435
|
+
await next();
|
|
436
|
+
return undefined;
|
|
437
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
//
|
|
5
|
+
// authorize / can — Hono PEP for HTTP routes.
|
|
6
|
+
//
|
|
7
|
+
// createAuthorizer(binding) returns helpers curried against an
|
|
8
|
+
// `AuthzCheckBinding` (the PDP):
|
|
9
|
+
//
|
|
10
|
+
// authorize(action, resourceGetter) → Hono middleware, 403s on deny
|
|
11
|
+
// can(c, action, resource) → boolean, for conditional logic
|
|
12
|
+
// check(c, action, resource) → full Decision, for advanced cases
|
|
13
|
+
// filterByCan(c, action, items, fn) → the items the principal may act on
|
|
14
|
+
//
|
|
15
|
+
// Use `authorize` on any mutating route. Use `can` inside handlers when
|
|
16
|
+
// the decision affects response shape (e.g. filter results, include
|
|
17
|
+
// admin-only fields, etc.).
|
|
18
|
+
//
|
|
19
|
+
|
|
20
|
+
import type { Context, MiddlewareHandler } from 'hono';
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
type Action,
|
|
24
|
+
type AuthzCheckBinding,
|
|
25
|
+
type Decision,
|
|
26
|
+
type Principal,
|
|
27
|
+
type ResourceRef,
|
|
28
|
+
denyPayload,
|
|
29
|
+
} from '@kindgi/authz';
|
|
30
|
+
|
|
31
|
+
import type { AppEnv } from '../types.js';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Callback that produces the resource being acted upon from the Hono
|
|
35
|
+
* context. Called at request time — can read path params, query, or
|
|
36
|
+
* body (if already parsed).
|
|
37
|
+
*/
|
|
38
|
+
export type ResourceGetter = (c: Context<AppEnv>) => ResourceRef | Promise<ResourceRef>;
|
|
39
|
+
|
|
40
|
+
export interface Authorizer {
|
|
41
|
+
readonly authorize: (action: Action, getResource: ResourceGetter) => MiddlewareHandler<AppEnv>;
|
|
42
|
+
readonly can: (c: Context<AppEnv>, action: Action, resource: ResourceRef) => Promise<boolean>;
|
|
43
|
+
readonly check: (c: Context<AppEnv>, action: Action, resource: ResourceRef) => Promise<Decision>;
|
|
44
|
+
/**
|
|
45
|
+
* List-filtering helper — takes items + a ref-extractor and returns
|
|
46
|
+
* only those items where the principal has `action` on the derived
|
|
47
|
+
* resource. Preserves input order. Empty in → empty out.
|
|
48
|
+
*
|
|
49
|
+
* Use in GET-list route handlers after fetching tenant-scoped rows;
|
|
50
|
+
* strips rows the caller can't read so the response only includes
|
|
51
|
+
* what they'd be allowed to touch.
|
|
52
|
+
*/
|
|
53
|
+
readonly filterByCan: <T>(
|
|
54
|
+
c: Context<AppEnv>,
|
|
55
|
+
action: Action,
|
|
56
|
+
items: readonly T[],
|
|
57
|
+
refFn: (item: T) => ResourceRef,
|
|
58
|
+
) => Promise<T[]>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createAuthorizer(binding: AuthzCheckBinding): Authorizer {
|
|
62
|
+
async function checkInternal(
|
|
63
|
+
c: Context<AppEnv>,
|
|
64
|
+
action: Action,
|
|
65
|
+
resource: ResourceRef,
|
|
66
|
+
): Promise<Decision> {
|
|
67
|
+
const principal = c.get('principal') as Principal | undefined;
|
|
68
|
+
if (principal === undefined) {
|
|
69
|
+
return {
|
|
70
|
+
allowed: false,
|
|
71
|
+
failing: 'actor',
|
|
72
|
+
reason: 'no principal on request (bearer/principal middleware did not run)',
|
|
73
|
+
evidence: {
|
|
74
|
+
action,
|
|
75
|
+
relation: '',
|
|
76
|
+
resource: `${resource.type}:${resource.id}`,
|
|
77
|
+
actorSubject: '',
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const requestId = c.get('requestId');
|
|
82
|
+
const ctx =
|
|
83
|
+
typeof requestId === 'string' && requestId.length > 0
|
|
84
|
+
? { correlationId: requestId }
|
|
85
|
+
: undefined;
|
|
86
|
+
return binding.check(principal, action, resource, ctx);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
check: checkInternal,
|
|
91
|
+
async can(c, action, resource) {
|
|
92
|
+
const d = await checkInternal(c, action, resource);
|
|
93
|
+
return d.allowed;
|
|
94
|
+
},
|
|
95
|
+
authorize(action, getResource) {
|
|
96
|
+
return async (c, next) => {
|
|
97
|
+
const resource = await getResource(c);
|
|
98
|
+
const decision = await checkInternal(c, action, resource);
|
|
99
|
+
if (!decision.allowed) {
|
|
100
|
+
const body = denyPayload(action, resource.type, resource.id, decision.reason);
|
|
101
|
+
c.status(403);
|
|
102
|
+
return c.json(body);
|
|
103
|
+
}
|
|
104
|
+
return next();
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
async filterByCan(c, action, items, refFn) {
|
|
108
|
+
if (items.length === 0) return [];
|
|
109
|
+
const principal = c.get('principal') as Principal | undefined;
|
|
110
|
+
if (principal === undefined) return [];
|
|
111
|
+
const refs = items.map(refFn);
|
|
112
|
+
const requestId = c.get('requestId');
|
|
113
|
+
const ctx =
|
|
114
|
+
typeof requestId === 'string' && requestId.length > 0
|
|
115
|
+
? { correlationId: requestId }
|
|
116
|
+
: undefined;
|
|
117
|
+
const decisions = await binding.checkBatch(principal, action, refs, ctx);
|
|
118
|
+
const out: (typeof items)[number][] = [];
|
|
119
|
+
for (let i = 0; i < items.length; i++) {
|
|
120
|
+
if (decisions[i]?.allowed) out.push(items[i] as (typeof items)[number]);
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type { MiddlewareHandler } from 'hono';
|
|
5
|
+
|
|
6
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Top-level catch-all. Any uncaught exception is translated to a
|
|
10
|
+
* `500 internal-server-error` wire error. Domain errors returned via
|
|
11
|
+
* `Result<T, E>` are handled per-route — this middleware only catches
|
|
12
|
+
* thrown exceptions (framework bugs, DB failures without Result wrap,
|
|
13
|
+
* etc.).
|
|
14
|
+
*
|
|
15
|
+
* The requestId embedded in the response body matches
|
|
16
|
+
* `middleware/request-id.ts`, so a caller can correlate.
|
|
17
|
+
*/
|
|
18
|
+
export function errorMapperMiddleware(): MiddlewareHandler {
|
|
19
|
+
return async (c, next) => {
|
|
20
|
+
try {
|
|
21
|
+
await next();
|
|
22
|
+
return;
|
|
23
|
+
} catch (cause) {
|
|
24
|
+
const requestId = (c.get('requestId') as string | undefined) ?? 'req-unknown';
|
|
25
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
26
|
+
const body = toWireError(
|
|
27
|
+
{
|
|
28
|
+
code: 'internal-server-error',
|
|
29
|
+
message: message.length > 0 ? message : 'Unhandled server error',
|
|
30
|
+
},
|
|
31
|
+
requestId,
|
|
32
|
+
);
|
|
33
|
+
c.status(statusFor('internal-server-error') as never);
|
|
34
|
+
return c.json(body);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|