@kindgi/api 0.0.0-bootstrap.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +216 -1
- package/dist/adapter-binding.d.ts +177 -0
- package/dist/adapter-binding.d.ts.map +1 -0
- package/dist/adapter-binding.js +12 -0
- package/dist/adapter-binding.js.map +1 -0
- package/dist/agent-binding.d.ts +207 -0
- package/dist/agent-binding.d.ts.map +1 -0
- package/dist/agent-binding.js +4 -0
- package/dist/agent-binding.js.map +1 -0
- package/dist/app.d.ts +770 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +397 -0
- package/dist/app.js.map +1 -0
- package/dist/capability-binding.d.ts +76 -0
- package/dist/capability-binding.d.ts.map +1 -0
- package/dist/capability-binding.js +4 -0
- package/dist/capability-binding.js.map +1 -0
- package/dist/cost-binding.d.ts +175 -0
- package/dist/cost-binding.d.ts.map +1 -0
- package/dist/cost-binding.js +13 -0
- package/dist/cost-binding.js.map +1 -0
- package/dist/deployment-binding.d.ts +201 -0
- package/dist/deployment-binding.d.ts.map +1 -0
- package/dist/deployment-binding.js +4 -0
- package/dist/deployment-binding.js.map +1 -0
- package/dist/env-binding.d.ts +132 -0
- package/dist/env-binding.d.ts.map +1 -0
- package/dist/env-binding.js +4 -0
- package/dist/env-binding.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +268 -0
- package/dist/errors.js.map +1 -0
- package/dist/eval-run-binding.d.ts +196 -0
- package/dist/eval-run-binding.d.ts.map +1 -0
- package/dist/eval-run-binding.js +16 -0
- package/dist/eval-run-binding.js.map +1 -0
- package/dist/eval-run-dispatcher.d.ts +131 -0
- package/dist/eval-run-dispatcher.d.ts.map +1 -0
- package/dist/eval-run-dispatcher.js +368 -0
- package/dist/eval-run-dispatcher.js.map +1 -0
- package/dist/eval-suite-binding.d.ts +227 -0
- package/dist/eval-suite-binding.d.ts.map +1 -0
- package/dist/eval-suite-binding.js +24 -0
- package/dist/eval-suite-binding.js.map +1 -0
- package/dist/event-bus-binding.d.ts +107 -0
- package/dist/event-bus-binding.d.ts.map +1 -0
- package/dist/event-bus-binding.js +5 -0
- package/dist/event-bus-binding.js.map +1 -0
- package/dist/flow-binding.d.ts +194 -0
- package/dist/flow-binding.d.ts.map +1 -0
- package/dist/flow-binding.js +4 -0
- package/dist/flow-binding.js.map +1 -0
- package/dist/guardrail-binding.d.ts +138 -0
- package/dist/guardrail-binding.d.ts.map +1 -0
- package/dist/guardrail-binding.js +4 -0
- package/dist/guardrail-binding.js.map +1 -0
- package/dist/handler-binding.d.ts +126 -0
- package/dist/handler-binding.d.ts.map +1 -0
- package/dist/handler-binding.js +4 -0
- package/dist/handler-binding.js.map +1 -0
- package/dist/hitl-binding.d.ts +115 -0
- package/dist/hitl-binding.d.ts.map +1 -0
- package/dist/hitl-binding.js +4 -0
- package/dist/hitl-binding.js.map +1 -0
- package/dist/identity-directory-binding.d.ts +116 -0
- package/dist/identity-directory-binding.d.ts.map +1 -0
- package/dist/identity-directory-binding.js +4 -0
- package/dist/identity-directory-binding.js.map +1 -0
- package/dist/identity-provider-binding.d.ts +184 -0
- package/dist/identity-provider-binding.d.ts.map +1 -0
- package/dist/identity-provider-binding.js +4 -0
- package/dist/identity-provider-binding.js.map +1 -0
- package/dist/image-registry-binding.d.ts +165 -0
- package/dist/image-registry-binding.d.ts.map +1 -0
- package/dist/image-registry-binding.js +4 -0
- package/dist/image-registry-binding.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/key-management-binding.d.ts +101 -0
- package/dist/key-management-binding.d.ts.map +1 -0
- package/dist/key-management-binding.js +4 -0
- package/dist/key-management-binding.js.map +1 -0
- package/dist/mcp-endpoint-binding.d.ts +312 -0
- package/dist/mcp-endpoint-binding.d.ts.map +1 -0
- package/dist/mcp-endpoint-binding.js +12 -0
- package/dist/mcp-endpoint-binding.js.map +1 -0
- package/dist/memory-binding.d.ts +209 -0
- package/dist/memory-binding.d.ts.map +1 -0
- package/dist/memory-binding.js +4 -0
- package/dist/memory-binding.js.map +1 -0
- package/dist/middleware/auth.d.ts +168 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +247 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/authorize.d.ts +26 -0
- package/dist/middleware/authorize.d.ts.map +1 -0
- package/dist/middleware/authorize.js +65 -0
- package/dist/middleware/authorize.js.map +1 -0
- package/dist/middleware/error-mapper.d.ts +20 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -0
- package/dist/middleware/error-mapper.js +34 -0
- package/dist/middleware/error-mapper.js.map +1 -0
- package/dist/middleware/idempotency.d.ts +43 -0
- package/dist/middleware/idempotency.d.ts.map +1 -0
- package/dist/middleware/idempotency.js +118 -0
- package/dist/middleware/idempotency.js.map +1 -0
- package/dist/middleware/principal.d.ts +4 -0
- package/dist/middleware/principal.d.ts.map +1 -0
- package/dist/middleware/principal.js +42 -0
- package/dist/middleware/principal.js.map +1 -0
- package/dist/middleware/public-run-routes.d.ts +16 -0
- package/dist/middleware/public-run-routes.d.ts.map +1 -0
- package/dist/middleware/public-run-routes.js +43 -0
- package/dist/middleware/public-run-routes.js.map +1 -0
- package/dist/middleware/request-id.d.ts +14 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +24 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/sigv4-verify.d.ts +64 -0
- package/dist/middleware/sigv4-verify.d.ts.map +1 -0
- package/dist/middleware/sigv4-verify.js +286 -0
- package/dist/middleware/sigv4-verify.js.map +1 -0
- package/dist/middleware/sigv4.d.ts +25 -0
- package/dist/middleware/sigv4.d.ts.map +1 -0
- package/dist/middleware/sigv4.js +120 -0
- package/dist/middleware/sigv4.js.map +1 -0
- package/dist/openapi/generate.d.ts +15 -0
- package/dist/openapi/generate.d.ts.map +1 -0
- package/dist/openapi/generate.js +241 -0
- package/dist/openapi/generate.js.map +1 -0
- package/dist/openapi/operations.d.ts +70 -0
- package/dist/openapi/operations.d.ts.map +1 -0
- package/dist/openapi/operations.js +5050 -0
- package/dist/openapi/operations.js.map +1 -0
- package/dist/openapi/schemas.d.ts +590 -0
- package/dist/openapi/schemas.d.ts.map +1 -0
- package/dist/openapi/schemas.js +5820 -0
- package/dist/openapi/schemas.js.map +1 -0
- package/dist/provenance-binding.d.ts +116 -0
- package/dist/provenance-binding.d.ts.map +1 -0
- package/dist/provenance-binding.js +31 -0
- package/dist/provenance-binding.js.map +1 -0
- package/dist/provider-binding.d.ts +174 -0
- package/dist/provider-binding.d.ts.map +1 -0
- package/dist/provider-binding.js +4 -0
- package/dist/provider-binding.js.map +1 -0
- package/dist/public-run-token.d.ts +97 -0
- package/dist/public-run-token.d.ts.map +1 -0
- package/dist/public-run-token.js +167 -0
- package/dist/public-run-token.js.map +1 -0
- package/dist/retention-binding.d.ts +69 -0
- package/dist/retention-binding.d.ts.map +1 -0
- package/dist/retention-binding.js +4 -0
- package/dist/retention-binding.js.map +1 -0
- package/dist/reviewer-binding.d.ts +84 -0
- package/dist/reviewer-binding.d.ts.map +1 -0
- package/dist/reviewer-binding.js +4 -0
- package/dist/reviewer-binding.js.map +1 -0
- package/dist/rotation-status-store.d.ts +96 -0
- package/dist/rotation-status-store.d.ts.map +1 -0
- package/dist/rotation-status-store.js +106 -0
- package/dist/rotation-status-store.js.map +1 -0
- package/dist/routes/adapters.d.ts +29 -0
- package/dist/routes/adapters.d.ts.map +1 -0
- package/dist/routes/adapters.js +230 -0
- package/dist/routes/adapters.js.map +1 -0
- package/dist/routes/agents.d.ts +17 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +342 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/approvals.d.ts +37 -0
- package/dist/routes/approvals.d.ts.map +1 -0
- package/dist/routes/approvals.js +551 -0
- package/dist/routes/approvals.js.map +1 -0
- package/dist/routes/artifacts.d.ts +25 -0
- package/dist/routes/artifacts.d.ts.map +1 -0
- package/dist/routes/artifacts.js +265 -0
- package/dist/routes/artifacts.js.map +1 -0
- package/dist/routes/audit.d.ts +6 -0
- package/dist/routes/audit.d.ts.map +1 -0
- package/dist/routes/audit.js +162 -0
- package/dist/routes/audit.js.map +1 -0
- package/dist/routes/auth.d.ts +47 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +630 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/capabilities.d.ts +14 -0
- package/dist/routes/capabilities.d.ts.map +1 -0
- package/dist/routes/capabilities.js +62 -0
- package/dist/routes/capabilities.js.map +1 -0
- package/dist/routes/compliance.d.ts +37 -0
- package/dist/routes/compliance.d.ts.map +1 -0
- package/dist/routes/compliance.js +321 -0
- package/dist/routes/compliance.js.map +1 -0
- package/dist/routes/conversations.d.ts +13 -0
- package/dist/routes/conversations.d.ts.map +1 -0
- package/dist/routes/conversations.js +295 -0
- package/dist/routes/conversations.js.map +1 -0
- package/dist/routes/cost.d.ts +24 -0
- package/dist/routes/cost.d.ts.map +1 -0
- package/dist/routes/cost.js +243 -0
- package/dist/routes/cost.js.map +1 -0
- package/dist/routes/deployments.d.ts +122 -0
- package/dist/routes/deployments.d.ts.map +1 -0
- package/dist/routes/deployments.js +1036 -0
- package/dist/routes/deployments.js.map +1 -0
- package/dist/routes/env.d.ts +62 -0
- package/dist/routes/env.d.ts.map +1 -0
- package/dist/routes/env.js +311 -0
- package/dist/routes/env.js.map +1 -0
- package/dist/routes/eval-runs.d.ts +28 -0
- package/dist/routes/eval-runs.d.ts.map +1 -0
- package/dist/routes/eval-runs.js +479 -0
- package/dist/routes/eval-runs.js.map +1 -0
- package/dist/routes/eval-suites.d.ts +24 -0
- package/dist/routes/eval-suites.d.ts.map +1 -0
- package/dist/routes/eval-suites.js +381 -0
- package/dist/routes/eval-suites.js.map +1 -0
- package/dist/routes/event-triggers.d.ts +12 -0
- package/dist/routes/event-triggers.d.ts.map +1 -0
- package/dist/routes/event-triggers.js +218 -0
- package/dist/routes/event-triggers.js.map +1 -0
- package/dist/routes/flows.d.ts +23 -0
- package/dist/routes/flows.d.ts.map +1 -0
- package/dist/routes/flows.js +344 -0
- package/dist/routes/flows.js.map +1 -0
- package/dist/routes/guardrails.d.ts +33 -0
- package/dist/routes/guardrails.d.ts.map +1 -0
- package/dist/routes/guardrails.js +236 -0
- package/dist/routes/guardrails.js.map +1 -0
- package/dist/routes/identity.d.ts +39 -0
- package/dist/routes/identity.d.ts.map +1 -0
- package/dist/routes/identity.js +138 -0
- package/dist/routes/identity.js.map +1 -0
- package/dist/routes/mcp.d.ts +23 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +727 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/memory.d.ts +16 -0
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +353 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/observations.d.ts +19 -0
- package/dist/routes/observations.d.ts.map +1 -0
- package/dist/routes/observations.js +135 -0
- package/dist/routes/observations.js.map +1 -0
- package/dist/routes/orgs.d.ts +24 -0
- package/dist/routes/orgs.d.ts.map +1 -0
- package/dist/routes/orgs.js +208 -0
- package/dist/routes/orgs.js.map +1 -0
- package/dist/routes/pagination.d.ts +18 -0
- package/dist/routes/pagination.d.ts.map +1 -0
- package/dist/routes/pagination.js +35 -0
- package/dist/routes/pagination.js.map +1 -0
- package/dist/routes/policies.d.ts +23 -0
- package/dist/routes/policies.d.ts.map +1 -0
- package/dist/routes/policies.js +314 -0
- package/dist/routes/policies.js.map +1 -0
- package/dist/routes/projects.d.ts +45 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +485 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/proposals.d.ts +24 -0
- package/dist/routes/proposals.d.ts.map +1 -0
- package/dist/routes/proposals.js +581 -0
- package/dist/routes/proposals.js.map +1 -0
- package/dist/routes/provenance.d.ts +34 -0
- package/dist/routes/provenance.d.ts.map +1 -0
- package/dist/routes/provenance.js +274 -0
- package/dist/routes/provenance.js.map +1 -0
- package/dist/routes/providers.d.ts +32 -0
- package/dist/routes/providers.d.ts.map +1 -0
- package/dist/routes/providers.js +490 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/public-run-tokens.d.ts +17 -0
- package/dist/routes/public-run-tokens.d.ts.map +1 -0
- package/dist/routes/public-run-tokens.js +69 -0
- package/dist/routes/public-run-tokens.js.map +1 -0
- package/dist/routes/retention.d.ts +19 -0
- package/dist/routes/retention.d.ts.map +1 -0
- package/dist/routes/retention.js +152 -0
- package/dist/routes/retention.js.map +1 -0
- package/dist/routes/reviewers.d.ts +5 -0
- package/dist/routes/reviewers.d.ts.map +1 -0
- package/dist/routes/reviewers.js +161 -0
- package/dist/routes/reviewers.js.map +1 -0
- package/dist/routes/runs.d.ts +34 -0
- package/dist/routes/runs.d.ts.map +1 -0
- package/dist/routes/runs.js +705 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/routes/s3.d.ts +31 -0
- package/dist/routes/s3.d.ts.map +1 -0
- package/dist/routes/s3.js +433 -0
- package/dist/routes/s3.js.map +1 -0
- package/dist/routes/schedules.d.ts +20 -0
- package/dist/routes/schedules.d.ts.map +1 -0
- package/dist/routes/schedules.js +234 -0
- package/dist/routes/schedules.js.map +1 -0
- package/dist/routes/scope-params.d.ts +57 -0
- package/dist/routes/scope-params.d.ts.map +1 -0
- package/dist/routes/scope-params.js +105 -0
- package/dist/routes/scope-params.js.map +1 -0
- package/dist/routes/secret-ref.d.ts +20 -0
- package/dist/routes/secret-ref.d.ts.map +1 -0
- package/dist/routes/secret-ref.js +42 -0
- package/dist/routes/secret-ref.js.map +1 -0
- package/dist/routes/secrets.d.ts +53 -0
- package/dist/routes/secrets.d.ts.map +1 -0
- package/dist/routes/secrets.js +715 -0
- package/dist/routes/secrets.js.map +1 -0
- package/dist/routes/signing-keys.d.ts +23 -0
- package/dist/routes/signing-keys.d.ts.map +1 -0
- package/dist/routes/signing-keys.js +212 -0
- package/dist/routes/signing-keys.js.map +1 -0
- package/dist/routes/sse.d.ts +58 -0
- package/dist/routes/sse.d.ts.map +1 -0
- package/dist/routes/sse.js +92 -0
- package/dist/routes/sse.js.map +1 -0
- package/dist/routes/teams.d.ts +30 -0
- package/dist/routes/teams.d.ts.map +1 -0
- package/dist/routes/teams.js +443 -0
- package/dist/routes/teams.js.map +1 -0
- package/dist/routes/tenant.d.ts +57 -0
- package/dist/routes/tenant.d.ts.map +1 -0
- package/dist/routes/tenant.js +352 -0
- package/dist/routes/tenant.js.map +1 -0
- package/dist/routes/tokens.d.ts +14 -0
- package/dist/routes/tokens.d.ts.map +1 -0
- package/dist/routes/tokens.js +231 -0
- package/dist/routes/tokens.js.map +1 -0
- package/dist/routes/tools.d.ts +33 -0
- package/dist/routes/tools.d.ts.map +1 -0
- package/dist/routes/tools.js +380 -0
- package/dist/routes/tools.js.map +1 -0
- package/dist/routes/webhook-endpoints.d.ts +10 -0
- package/dist/routes/webhook-endpoints.d.ts.map +1 -0
- package/dist/routes/webhook-endpoints.js +407 -0
- package/dist/routes/webhook-endpoints.js.map +1 -0
- package/dist/routes/webhooks.d.ts +21 -0
- package/dist/routes/webhooks.d.ts.map +1 -0
- package/dist/routes/webhooks.js +228 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/s3-credential-binding.d.ts +54 -0
- package/dist/s3-credential-binding.d.ts.map +1 -0
- package/dist/s3-credential-binding.js +4 -0
- package/dist/s3-credential-binding.js.map +1 -0
- package/dist/secrets-binding.d.ts +281 -0
- package/dist/secrets-binding.d.ts.map +1 -0
- package/dist/secrets-binding.js +10 -0
- package/dist/secrets-binding.js.map +1 -0
- package/dist/secrets-provider-binding.d.ts +164 -0
- package/dist/secrets-provider-binding.d.ts.map +1 -0
- package/dist/secrets-provider-binding.js +4 -0
- package/dist/secrets-provider-binding.js.map +1 -0
- package/dist/session-store-binding.d.ts +148 -0
- package/dist/session-store-binding.d.ts.map +1 -0
- package/dist/session-store-binding.js +4 -0
- package/dist/session-store-binding.js.map +1 -0
- package/dist/signing-key-binding.d.ts +210 -0
- package/dist/signing-key-binding.d.ts.map +1 -0
- package/dist/signing-key-binding.js +4 -0
- package/dist/signing-key-binding.js.map +1 -0
- package/dist/state-store-binding.d.ts +53 -0
- package/dist/state-store-binding.d.ts.map +1 -0
- package/dist/state-store-binding.js +38 -0
- package/dist/state-store-binding.js.map +1 -0
- package/dist/supervisor-binding.d.ts +526 -0
- package/dist/supervisor-binding.d.ts.map +1 -0
- package/dist/supervisor-binding.js +4 -0
- package/dist/supervisor-binding.js.map +1 -0
- package/dist/tenant-host-access.d.ts +41 -0
- package/dist/tenant-host-access.d.ts.map +1 -0
- package/dist/tenant-host-access.js +42 -0
- package/dist/tenant-host-access.js.map +1 -0
- package/dist/token-admin.d.ts +99 -0
- package/dist/token-admin.d.ts.map +1 -0
- package/dist/token-admin.js +4 -0
- package/dist/token-admin.js.map +1 -0
- package/dist/tool-binding.d.ts +247 -0
- package/dist/tool-binding.d.ts.map +1 -0
- package/dist/tool-binding.js +4 -0
- package/dist/tool-binding.js.map +1 -0
- package/dist/trigger-binding.d.ts +13 -0
- package/dist/trigger-binding.d.ts.map +1 -0
- package/dist/trigger-binding.js +4 -0
- package/dist/trigger-binding.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook-endpoint-binding.d.ts +230 -0
- package/dist/webhook-endpoint-binding.d.ts.map +1 -0
- package/dist/webhook-endpoint-binding.js +12 -0
- package/dist/webhook-endpoint-binding.js.map +1 -0
- package/dist/xml.d.ts +79 -0
- package/dist/xml.d.ts.map +1 -0
- package/dist/xml.js +115 -0
- package/dist/xml.js.map +1 -0
- package/openapi.json +29649 -0
- package/package.json +76 -4
- package/scripts/emit-openapi.mjs +44 -0
- package/src/adapter-binding.ts +204 -0
- package/src/agent-binding.ts +231 -0
- package/src/app.ts +1286 -0
- package/src/capability-binding.ts +83 -0
- package/src/cost-binding.ts +213 -0
- package/src/deployment-binding.ts +225 -0
- package/src/env-binding.ts +140 -0
- package/src/errors.ts +295 -0
- package/src/eval-run-binding.ts +209 -0
- package/src/eval-run-dispatcher.ts +497 -0
- package/src/eval-suite-binding.ts +257 -0
- package/src/event-bus-binding.ts +127 -0
- package/src/flow-binding.ts +213 -0
- package/src/guardrail-binding.ts +151 -0
- package/src/handler-binding.ts +132 -0
- package/src/hitl-binding.ts +172 -0
- package/src/identity-directory-binding.ts +128 -0
- package/src/identity-provider-binding.ts +203 -0
- package/src/image-registry-binding.ts +193 -0
- package/src/index.ts +606 -0
- package/src/key-management-binding.ts +91 -0
- package/src/mcp-endpoint-binding.ts +311 -0
- package/src/memory-binding.ts +239 -0
- package/src/middleware/auth.ts +437 -0
- package/src/middleware/authorize.ts +125 -0
- package/src/middleware/error-mapper.ts +40 -0
- package/src/middleware/idempotency.ts +160 -0
- package/src/middleware/principal.ts +64 -0
- package/src/middleware/public-run-routes.ts +50 -0
- package/src/middleware/request-id.ts +28 -0
- package/src/middleware/sigv4-verify.ts +374 -0
- package/src/middleware/sigv4.ts +165 -0
- package/src/openapi/generate.ts +307 -0
- package/src/openapi/operations.ts +5444 -0
- package/src/openapi/schemas.ts +6363 -0
- package/src/provenance-binding.ts +169 -0
- package/src/provider-binding.ts +196 -0
- package/src/public-run-token.ts +263 -0
- package/src/retention-binding.ts +78 -0
- package/src/reviewer-binding.ts +99 -0
- package/src/rotation-status-store.ts +209 -0
- package/src/routes/adapters.ts +319 -0
- package/src/routes/agents.ts +424 -0
- package/src/routes/approvals.ts +759 -0
- package/src/routes/artifacts.ts +317 -0
- package/src/routes/audit.ts +219 -0
- package/src/routes/auth.ts +806 -0
- package/src/routes/capabilities.ts +79 -0
- package/src/routes/compliance.ts +482 -0
- package/src/routes/conversations.ts +369 -0
- package/src/routes/cost.ts +327 -0
- package/src/routes/deployments.ts +1493 -0
- package/src/routes/env.ts +429 -0
- package/src/routes/eval-runs.ts +631 -0
- package/src/routes/eval-suites.ts +490 -0
- package/src/routes/event-triggers.ts +283 -0
- package/src/routes/flows.ts +423 -0
- package/src/routes/guardrails.ts +320 -0
- package/src/routes/identity.ts +203 -0
- package/src/routes/mcp.ts +940 -0
- package/src/routes/memory.ts +430 -0
- package/src/routes/observations.ts +175 -0
- package/src/routes/orgs.ts +273 -0
- package/src/routes/pagination.ts +51 -0
- package/src/routes/policies.ts +413 -0
- package/src/routes/projects.ts +634 -0
- package/src/routes/proposals.ts +719 -0
- package/src/routes/provenance.ts +406 -0
- package/src/routes/providers.ts +624 -0
- package/src/routes/public-run-tokens.ts +104 -0
- package/src/routes/retention.ts +193 -0
- package/src/routes/reviewers.ts +209 -0
- package/src/routes/runs.ts +892 -0
- package/src/routes/s3.ts +519 -0
- package/src/routes/schedules.ts +300 -0
- package/src/routes/scope-params.ts +133 -0
- package/src/routes/secret-ref.ts +52 -0
- package/src/routes/secrets.ts +975 -0
- package/src/routes/signing-keys.ts +259 -0
- package/src/routes/sse.ts +148 -0
- package/src/routes/teams.ts +584 -0
- package/src/routes/tenant.ts +530 -0
- package/src/routes/tokens.ts +285 -0
- package/src/routes/tools.ts +491 -0
- package/src/routes/webhook-endpoints.ts +534 -0
- package/src/routes/webhooks.ts +296 -0
- package/src/s3-credential-binding.ts +58 -0
- package/src/secrets-binding.ts +308 -0
- package/src/secrets-provider-binding.ts +167 -0
- package/src/session-store-binding.ts +163 -0
- package/src/signing-key-binding.ts +235 -0
- package/src/state-store-binding.ts +84 -0
- package/src/supervisor-binding.ts +554 -0
- package/src/tenant-host-access.ts +62 -0
- package/src/token-admin.ts +104 -0
- package/src/tool-binding.ts +274 -0
- package/src/trigger-binding.ts +38 -0
- package/src/types.ts +74 -0
- package/src/webhook-endpoint-binding.ts +246 -0
- package/src/xml.ts +196 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
import type { Context } from 'hono';
|
|
6
|
+
|
|
7
|
+
import type { Cursor, TenantId, TriggerId } from '@kindgi/types';
|
|
8
|
+
|
|
9
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
10
|
+
import type {
|
|
11
|
+
EventTriggerRecord,
|
|
12
|
+
RegisterEventTriggerInput,
|
|
13
|
+
TriggerRegistryBinding,
|
|
14
|
+
UpdateEventTriggerInput,
|
|
15
|
+
} from '../trigger-binding.js';
|
|
16
|
+
import type { AppEnv } from '../types.js';
|
|
17
|
+
import { clampLimit } from './pagination.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Event triggers — fire a flow run when a matching event arrives on
|
|
21
|
+
* the framework event bus.
|
|
22
|
+
*
|
|
23
|
+
* Seven routes, mirroring the schedules surface. This surface registers
|
|
24
|
+
* triggers; it does not publish events.
|
|
25
|
+
*/
|
|
26
|
+
export function eventTriggersRouter(binding: TriggerRegistryBinding): Hono<AppEnv> {
|
|
27
|
+
const r = new Hono<AppEnv>();
|
|
28
|
+
|
|
29
|
+
// ---------- POST / (register) ----------
|
|
30
|
+
r.post('/', async (c) => {
|
|
31
|
+
const requestId = c.get('requestId');
|
|
32
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
33
|
+
|
|
34
|
+
const parsed = await parseJsonObject(c, requestId);
|
|
35
|
+
if (parsed.kind === 'err') return parsed.response;
|
|
36
|
+
const body = parsed.value;
|
|
37
|
+
|
|
38
|
+
const flowId = requireString(body, 'flowId');
|
|
39
|
+
const flowVersion = requireString(body, 'flowVersion');
|
|
40
|
+
const eventKind = requireString(body.config, 'config.eventKind');
|
|
41
|
+
if (flowId.kind === 'err') return bad(c, requestId, flowId.message);
|
|
42
|
+
if (flowVersion.kind === 'err') return bad(c, requestId, flowVersion.message);
|
|
43
|
+
if (eventKind.kind === 'err') return bad(c, requestId, eventKind.message);
|
|
44
|
+
|
|
45
|
+
const rawConfig = (body.config ?? {}) as Record<string, unknown>;
|
|
46
|
+
const registerInput: RegisterEventTriggerInput = {
|
|
47
|
+
kind: 'event',
|
|
48
|
+
tenantId,
|
|
49
|
+
flowId: flowId.value,
|
|
50
|
+
flowVersion: flowVersion.value,
|
|
51
|
+
config: {
|
|
52
|
+
eventKind: eventKind.value,
|
|
53
|
+
...('input' in rawConfig && { input: rawConfig.input }),
|
|
54
|
+
},
|
|
55
|
+
...(typeof body.label === 'string' && body.label.length > 0 && { label: body.label }),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const result = await binding.register(registerInput);
|
|
59
|
+
if (result.kind === 'err') {
|
|
60
|
+
c.status(statusFor(result.error.code) as never);
|
|
61
|
+
return c.json(
|
|
62
|
+
toWireError({ code: result.error.code, message: result.error.message }, requestId),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
c.status(201);
|
|
66
|
+
return c.json(serializeEventTrigger(result.value as EventTriggerRecord));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ---------- GET / (list) ----------
|
|
70
|
+
r.get('/', async (c) => {
|
|
71
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
72
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
73
|
+
const cursorRaw = c.req.query('cursor');
|
|
74
|
+
const statusRaw = c.req.query('status');
|
|
75
|
+
|
|
76
|
+
let statusFilter: 'active' | 'paused' | undefined;
|
|
77
|
+
if (statusRaw === 'active' || statusRaw === 'paused') statusFilter = statusRaw;
|
|
78
|
+
|
|
79
|
+
const page = await binding.list({
|
|
80
|
+
tenantId,
|
|
81
|
+
kind: 'event',
|
|
82
|
+
limit,
|
|
83
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
84
|
+
...(statusFilter !== undefined && { status: statusFilter }),
|
|
85
|
+
});
|
|
86
|
+
return c.json({
|
|
87
|
+
data: page.data.map((row) => serializeEventTrigger(row as EventTriggerRecord)),
|
|
88
|
+
hasMore: page.nextCursor !== undefined,
|
|
89
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// ---------- GET /:triggerId (get) ----------
|
|
94
|
+
r.get('/:triggerId', async (c) => {
|
|
95
|
+
const requestId = c.get('requestId');
|
|
96
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
97
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
98
|
+
|
|
99
|
+
const rec = await binding.get({ tenantId, triggerId });
|
|
100
|
+
if (rec === null || rec.kind !== 'event') return notFound(c, requestId, triggerId);
|
|
101
|
+
return c.json(serializeEventTrigger(rec));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ---------- PATCH /:triggerId (update) ----------
|
|
105
|
+
r.patch('/:triggerId', async (c) => {
|
|
106
|
+
const requestId = c.get('requestId');
|
|
107
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
108
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
109
|
+
|
|
110
|
+
const parsed = await parseJsonObject(c, requestId);
|
|
111
|
+
if (parsed.kind === 'err') return parsed.response;
|
|
112
|
+
const body = parsed.value;
|
|
113
|
+
|
|
114
|
+
const patchConfig = body.config as Record<string, unknown> | undefined;
|
|
115
|
+
const cfg: Partial<{ eventKind: string; input: unknown }> = {};
|
|
116
|
+
if (patchConfig !== undefined) {
|
|
117
|
+
if (typeof patchConfig.eventKind === 'string') cfg.eventKind = patchConfig.eventKind;
|
|
118
|
+
if ('input' in patchConfig) cfg.input = patchConfig.input;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const updateInput: UpdateEventTriggerInput = {
|
|
122
|
+
kind: 'event',
|
|
123
|
+
tenantId,
|
|
124
|
+
triggerId,
|
|
125
|
+
...(Object.keys(cfg).length > 0 && { config: cfg }),
|
|
126
|
+
...('label' in body && { label: body.label === null ? null : (body.label as string) }),
|
|
127
|
+
...(typeof body.flowVersion === 'string' && { flowVersion: body.flowVersion }),
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const result = await binding.update(updateInput);
|
|
131
|
+
if (result.kind === 'err') {
|
|
132
|
+
c.status(statusFor(result.error.code) as never);
|
|
133
|
+
return c.json(
|
|
134
|
+
toWireError(
|
|
135
|
+
{
|
|
136
|
+
code: result.error.code,
|
|
137
|
+
message: result.error.message,
|
|
138
|
+
triggerId: triggerId as unknown as string,
|
|
139
|
+
},
|
|
140
|
+
requestId,
|
|
141
|
+
),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
return c.json(serializeEventTrigger(result.value as EventTriggerRecord));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ---------- POST /:triggerId/pause ----------
|
|
148
|
+
r.post('/:triggerId/pause', async (c) => {
|
|
149
|
+
const requestId = c.get('requestId');
|
|
150
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
151
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
152
|
+
const result = await binding.pause({ tenantId, triggerId });
|
|
153
|
+
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
154
|
+
return c.json(serializeEventTrigger(result.value as EventTriggerRecord));
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// ---------- POST /:triggerId/resume ----------
|
|
158
|
+
r.post('/:triggerId/resume', async (c) => {
|
|
159
|
+
const requestId = c.get('requestId');
|
|
160
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
161
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
162
|
+
const result = await binding.resume({ tenantId, triggerId });
|
|
163
|
+
if (result.kind === 'err') return lifecycleError(c, requestId, result.error, triggerId);
|
|
164
|
+
return c.json(serializeEventTrigger(result.value as EventTriggerRecord));
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// ---------- POST /:triggerId/unregister (soft delete) ----------
|
|
168
|
+
r.post('/:triggerId/unregister', async (c) => {
|
|
169
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
170
|
+
const triggerId = c.req.param('triggerId') as TriggerId;
|
|
171
|
+
const outcome = await binding.unregister({ tenantId, triggerId });
|
|
172
|
+
return c.json({
|
|
173
|
+
eventTriggerId: triggerId as unknown as string,
|
|
174
|
+
unregistered: outcome.unregistered,
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return r;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function serializeEventTrigger(r: EventTriggerRecord): Record<string, unknown> {
|
|
182
|
+
return {
|
|
183
|
+
eventTriggerId: r.triggerId as unknown as string,
|
|
184
|
+
triggerId: r.triggerId as unknown as string,
|
|
185
|
+
flowId: r.flowId,
|
|
186
|
+
flowVersion: r.flowVersion,
|
|
187
|
+
eventKind: r.config.eventKind,
|
|
188
|
+
...(r.config.input !== undefined && { input: r.config.input }),
|
|
189
|
+
label: r.label,
|
|
190
|
+
status: r.status,
|
|
191
|
+
lastFiredAt: r.lastFiredAt,
|
|
192
|
+
createdAt: r.createdAt,
|
|
193
|
+
updatedAt: r.updatedAt,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
type ParseOk<T> = { readonly kind: 'ok'; readonly value: T };
|
|
198
|
+
type ParseErr = { readonly kind: 'err'; readonly response: Response };
|
|
199
|
+
|
|
200
|
+
async function parseJsonObject(
|
|
201
|
+
c: Context<AppEnv>,
|
|
202
|
+
requestId: string,
|
|
203
|
+
): Promise<ParseOk<Record<string, unknown>> | ParseErr> {
|
|
204
|
+
let body: unknown;
|
|
205
|
+
try {
|
|
206
|
+
body = await c.req.json();
|
|
207
|
+
} catch {
|
|
208
|
+
c.status(statusFor('bad-input') as never);
|
|
209
|
+
return {
|
|
210
|
+
kind: 'err',
|
|
211
|
+
response: c.json(
|
|
212
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
213
|
+
),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
217
|
+
c.status(statusFor('bad-input') as never);
|
|
218
|
+
return {
|
|
219
|
+
kind: 'err',
|
|
220
|
+
response: c.json(
|
|
221
|
+
toWireError(
|
|
222
|
+
{ code: 'bad-input', message: 'Request body must be a JSON object' },
|
|
223
|
+
requestId,
|
|
224
|
+
),
|
|
225
|
+
),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return { kind: 'ok', value: body as Record<string, unknown> };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function requireString(
|
|
232
|
+
obj: unknown,
|
|
233
|
+
path: string,
|
|
234
|
+
):
|
|
235
|
+
| { readonly kind: 'ok'; readonly value: string }
|
|
236
|
+
| { readonly kind: 'err'; readonly message: string } {
|
|
237
|
+
const parts = path.split('.');
|
|
238
|
+
let cur: unknown = obj;
|
|
239
|
+
for (const part of parts) {
|
|
240
|
+
if (cur === null || typeof cur !== 'object') {
|
|
241
|
+
return { kind: 'err', message: `\`${path}\` is required` };
|
|
242
|
+
}
|
|
243
|
+
cur = (cur as Record<string, unknown>)[part];
|
|
244
|
+
}
|
|
245
|
+
if (typeof cur !== 'string' || cur.length === 0) {
|
|
246
|
+
return { kind: 'err', message: `\`${path}\` is required` };
|
|
247
|
+
}
|
|
248
|
+
return { kind: 'ok', value: cur };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function bad(c: Context<AppEnv>, requestId: string, message: string): Response {
|
|
252
|
+
c.status(statusFor('bad-input') as never);
|
|
253
|
+
return c.json(toWireError({ code: 'bad-input', message }, requestId));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function notFound(c: Context<AppEnv>, requestId: string, triggerId: TriggerId): Response {
|
|
257
|
+
c.status(statusFor('trigger-not-found') as never);
|
|
258
|
+
return c.json(
|
|
259
|
+
toWireError(
|
|
260
|
+
{
|
|
261
|
+
code: 'trigger-not-found',
|
|
262
|
+
message: `No trigger with id "${triggerId as unknown as string}"`,
|
|
263
|
+
triggerId: triggerId as unknown as string,
|
|
264
|
+
},
|
|
265
|
+
requestId,
|
|
266
|
+
),
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function lifecycleError(
|
|
271
|
+
c: Context<AppEnv>,
|
|
272
|
+
requestId: string,
|
|
273
|
+
error: { readonly code: string; readonly message: string },
|
|
274
|
+
triggerId: TriggerId,
|
|
275
|
+
): Response {
|
|
276
|
+
c.status(statusFor(error.code) as never);
|
|
277
|
+
return c.json(
|
|
278
|
+
toWireError(
|
|
279
|
+
{ code: error.code, message: error.message, triggerId: triggerId as unknown as string },
|
|
280
|
+
requestId,
|
|
281
|
+
),
|
|
282
|
+
);
|
|
283
|
+
}
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import { Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
import { type Principal, ref, tuplesForCreate } from '@kindgi/authz';
|
|
7
|
+
import { type Flow, type FlowError, loadFlow } from '@kindgi/flow';
|
|
8
|
+
import type { Cursor, FlowId, ProjectId, TenantId, UserId } from '@kindgi/types';
|
|
9
|
+
|
|
10
|
+
import { statusFor, toWireError } from '../errors.js';
|
|
11
|
+
import type { FlowRegistryBinding } from '../flow-binding.js';
|
|
12
|
+
import type { Authorizer } from '../middleware/authorize.js';
|
|
13
|
+
import type { AppEnv } from '../types.js';
|
|
14
|
+
import { clampLimit } from './pagination.js';
|
|
15
|
+
import { parseScopeParams } from './scope-params.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Flows resource routes.
|
|
19
|
+
*
|
|
20
|
+
* Registry storage is caller-plugged via `FlowRegistryBinding`,
|
|
21
|
+
* mirroring `AgentRegistryBinding` 1:1. The API package does not own
|
|
22
|
+
* persistence — the binding implementation supplies the store (tests
|
|
23
|
+
* wrap an in-memory `Map`-backed adapter).
|
|
24
|
+
*
|
|
25
|
+
* Publish is data-as-code: the body is a full `Flow` definition
|
|
26
|
+
* (`@kindgi/specs/flow.schema.json`). Validation runs through
|
|
27
|
+
* `@kindgi/flow.loadFlow(...)` so a flow published through the
|
|
28
|
+
* API is byte-identical to one constructed in-process.
|
|
29
|
+
*
|
|
30
|
+
* Run initiation stays at `POST /v1/runs` (one primitive,
|
|
31
|
+
* discriminated subject). No
|
|
32
|
+
* `/v1/flows/:flowId/run` route is added here.
|
|
33
|
+
*/
|
|
34
|
+
export function flowsRouter(binding: FlowRegistryBinding, authorizer?: Authorizer): Hono<AppEnv> {
|
|
35
|
+
const r = new Hono<AppEnv>();
|
|
36
|
+
|
|
37
|
+
// Authorization — mirrors agents 1:1. Check the resource directly;
|
|
38
|
+
// permissions cascade from the parent project because publish writes
|
|
39
|
+
// the parent tuple in the same transaction.
|
|
40
|
+
if (authorizer !== undefined) {
|
|
41
|
+
r.use('/', async (c, next) => {
|
|
42
|
+
if (c.req.method !== 'POST') return next();
|
|
43
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
44
|
+
const mw = authorizer.authorize('admin', async () => {
|
|
45
|
+
try {
|
|
46
|
+
const body = await c.req.json();
|
|
47
|
+
const pid =
|
|
48
|
+
body !== null && typeof body === 'object'
|
|
49
|
+
? (body as Record<string, unknown>).projectId
|
|
50
|
+
: undefined;
|
|
51
|
+
if (typeof pid === 'string' && pid.length > 0) return ref('project', pid);
|
|
52
|
+
} catch {
|
|
53
|
+
// POST handler validates + returns 400
|
|
54
|
+
}
|
|
55
|
+
return ref('tenant', tenantId as unknown as string);
|
|
56
|
+
});
|
|
57
|
+
return mw(c, next);
|
|
58
|
+
});
|
|
59
|
+
r.use('/', async (c, next) => {
|
|
60
|
+
if (c.req.method !== 'GET') return next();
|
|
61
|
+
// A project filter needs read on that project. Parse it as the
|
|
62
|
+
// handler does (`?scopeKind=project&scopeId=`).
|
|
63
|
+
const s = parseScopeParams((n) => c.req.query(n), {
|
|
64
|
+
tenantId: c.get('tenantId') as TenantId,
|
|
65
|
+
});
|
|
66
|
+
if (s.kind !== 'ok' || s.scope?.kind !== 'project') return next();
|
|
67
|
+
const scopeProjectId = s.scope.projectId as unknown as string;
|
|
68
|
+
const mw = authorizer.authorize('read', () => ref('project', scopeProjectId));
|
|
69
|
+
return mw(c, next);
|
|
70
|
+
});
|
|
71
|
+
r.use('/:flowId/*', async (c, next) => {
|
|
72
|
+
const action = c.req.method === 'GET' ? 'read' : 'admin';
|
|
73
|
+
const flowId = c.req.param('flowId') ?? '';
|
|
74
|
+
const mw = authorizer.authorize(action, () => ref('flow', flowId));
|
|
75
|
+
return mw(c, next);
|
|
76
|
+
});
|
|
77
|
+
r.use('/:flowId', async (c, next) => {
|
|
78
|
+
if (c.req.method !== 'GET') return next();
|
|
79
|
+
const flowId = c.req.param('flowId') ?? '';
|
|
80
|
+
const mw = authorizer.authorize('read', () => ref('flow', flowId));
|
|
81
|
+
return mw(c, next);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ---------- GET / (list, cursor-paginated) ----------
|
|
86
|
+
r.get('/', async (c) => {
|
|
87
|
+
const requestId = c.get('requestId');
|
|
88
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
89
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
90
|
+
|
|
91
|
+
const cursorRaw = c.req.query('cursor');
|
|
92
|
+
const nameRaw = c.req.query('name');
|
|
93
|
+
|
|
94
|
+
const scopeParsed = parseScopeParams(c.req.query(), { tenantId });
|
|
95
|
+
if (scopeParsed.kind === 'err') {
|
|
96
|
+
c.status(statusFor('scope-invalid') as never);
|
|
97
|
+
return c.json(
|
|
98
|
+
toWireError({ code: 'scope-invalid', message: scopeParsed.message }, requestId),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const page = await binding.list({
|
|
103
|
+
tenantId,
|
|
104
|
+
limit,
|
|
105
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
106
|
+
...(nameRaw !== undefined && nameRaw.length > 0 && { nameFilter: nameRaw }),
|
|
107
|
+
...(scopeParsed.scope !== undefined && { scope: scopeParsed.scope }),
|
|
108
|
+
...(scopeParsed.inherit !== undefined && { inherit: scopeParsed.inherit }),
|
|
109
|
+
});
|
|
110
|
+
return c.json({
|
|
111
|
+
data: page.data.map(serializeGraph),
|
|
112
|
+
hasMore: page.nextCursor !== undefined,
|
|
113
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ---------- GET /:flowId (latest version) ----------
|
|
118
|
+
r.get('/:flowId', async (c) => {
|
|
119
|
+
const requestId = c.get('requestId');
|
|
120
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
121
|
+
const flowId = c.req.param('flowId') as FlowId;
|
|
122
|
+
|
|
123
|
+
const flow = await binding.get({ tenantId, flowId });
|
|
124
|
+
if (flow === null) {
|
|
125
|
+
// 410 gone (head exists, no active version) vs 404 not-found
|
|
126
|
+
// (never registered).
|
|
127
|
+
const exists = await binding.headExists({ tenantId, flowId });
|
|
128
|
+
if (exists) {
|
|
129
|
+
c.status(statusFor('flow-gone') as never);
|
|
130
|
+
return c.json(
|
|
131
|
+
toWireError(
|
|
132
|
+
{
|
|
133
|
+
code: 'flow-gone',
|
|
134
|
+
message: `Flow "${flowId as unknown as string}" has no active versions; reinstate a tombstoned version or publish a new one`,
|
|
135
|
+
flowId: flowId as unknown as string,
|
|
136
|
+
},
|
|
137
|
+
requestId,
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
c.status(statusFor('flow-not-found') as never);
|
|
142
|
+
return c.json(
|
|
143
|
+
toWireError(
|
|
144
|
+
{
|
|
145
|
+
code: 'flow-not-found',
|
|
146
|
+
message: `No flow registered with id "${flowId as unknown as string}"`,
|
|
147
|
+
flowId: flowId as unknown as string,
|
|
148
|
+
},
|
|
149
|
+
requestId,
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return c.json(serializeGraph(flow));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// ---------- GET /:flowId/versions (list versions) ----------
|
|
157
|
+
r.get('/:flowId/versions', async (c) => {
|
|
158
|
+
const requestId = c.get('requestId');
|
|
159
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
160
|
+
const flowId = c.req.param('flowId') as FlowId;
|
|
161
|
+
const limit = clampLimit(c.req.query('limit'));
|
|
162
|
+
const cursorRaw = c.req.query('cursor');
|
|
163
|
+
|
|
164
|
+
// Confirm the id exists at all — an empty versions list from the
|
|
165
|
+
// binding is ambiguous (no versions vs. unknown id), so we do a
|
|
166
|
+
// preliminary `get` to flip an unknown id to a `404`.
|
|
167
|
+
const latest = await binding.get({ tenantId, flowId });
|
|
168
|
+
if (latest === null) {
|
|
169
|
+
c.status(statusFor('flow-not-found') as never);
|
|
170
|
+
return c.json(
|
|
171
|
+
toWireError(
|
|
172
|
+
{
|
|
173
|
+
code: 'flow-not-found',
|
|
174
|
+
message: `No flow registered with id "${flowId as unknown as string}"`,
|
|
175
|
+
flowId: flowId as unknown as string,
|
|
176
|
+
},
|
|
177
|
+
requestId,
|
|
178
|
+
),
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const page = await binding.listVersions({
|
|
183
|
+
tenantId,
|
|
184
|
+
flowId,
|
|
185
|
+
limit,
|
|
186
|
+
...(cursorRaw !== undefined && cursorRaw.length > 0 && { cursor: cursorRaw as Cursor }),
|
|
187
|
+
});
|
|
188
|
+
return c.json({
|
|
189
|
+
data: page.data.map(serializeGraph),
|
|
190
|
+
hasMore: page.nextCursor !== undefined,
|
|
191
|
+
...(page.nextCursor !== undefined && { nextCursor: page.nextCursor as unknown as string }),
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// ---------- GET /:flowId/versions/:version ----------
|
|
196
|
+
r.get('/:flowId/versions/:version', async (c) => {
|
|
197
|
+
const requestId = c.get('requestId');
|
|
198
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
199
|
+
const flowId = c.req.param('flowId') as FlowId;
|
|
200
|
+
const version = c.req.param('version');
|
|
201
|
+
|
|
202
|
+
const flow = await binding.getVersion({ tenantId, flowId, version });
|
|
203
|
+
if (flow === null) {
|
|
204
|
+
c.status(statusFor('flow-not-found') as never);
|
|
205
|
+
return c.json(
|
|
206
|
+
toWireError(
|
|
207
|
+
{
|
|
208
|
+
code: 'flow-not-found',
|
|
209
|
+
message: `No flow "${flowId as unknown as string}" at version "${version}"`,
|
|
210
|
+
flowId: flowId as unknown as string,
|
|
211
|
+
version: version,
|
|
212
|
+
},
|
|
213
|
+
requestId,
|
|
214
|
+
),
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return c.json(serializeGraph(flow));
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// ---------- POST / (publish) ----------
|
|
221
|
+
r.post('/', async (c) => {
|
|
222
|
+
const requestId = c.get('requestId');
|
|
223
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
224
|
+
|
|
225
|
+
let body: unknown;
|
|
226
|
+
try {
|
|
227
|
+
body = await c.req.json();
|
|
228
|
+
} catch {
|
|
229
|
+
c.status(statusFor('bad-input') as never);
|
|
230
|
+
return c.json(
|
|
231
|
+
toWireError({ code: 'bad-input', message: 'Request body must be valid JSON' }, requestId),
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
if (body === null || typeof body !== 'object') {
|
|
235
|
+
c.status(statusFor('bad-input') as never);
|
|
236
|
+
return c.json(
|
|
237
|
+
toWireError({ code: 'bad-input', message: 'Request body must be an object' }, requestId),
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// `projectId` is REQUIRED on the POST body.
|
|
242
|
+
// Missing / empty / non-string → 400 bad-input. Absent from the
|
|
243
|
+
// flow-shape validator on purpose — the caller controls what
|
|
244
|
+
// project the flow lands in; the flow definition itself is
|
|
245
|
+
// project-agnostic.
|
|
246
|
+
const bodyObj = body as Record<string, unknown>;
|
|
247
|
+
const projectIdRaw = bodyObj.projectId;
|
|
248
|
+
if (typeof projectIdRaw !== 'string' || projectIdRaw.length === 0) {
|
|
249
|
+
c.status(statusFor('bad-input') as never);
|
|
250
|
+
return c.json(
|
|
251
|
+
toWireError({ code: 'bad-input', message: '`projectId` is required' }, requestId),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
const projectId = projectIdRaw as ProjectId;
|
|
255
|
+
|
|
256
|
+
// Validate via loadFlow — same rules as the runtime loader, so a
|
|
257
|
+
// flow published through the API is byte-identical to one
|
|
258
|
+
// constructed in-process. `loadFlow` returns a Result rather than
|
|
259
|
+
// throwing. `projectId` is stripped from the wire body before
|
|
260
|
+
// validation — the flow definition itself is project-agnostic
|
|
261
|
+
// (loadFlow rejects unknown top-level keys).
|
|
262
|
+
const { projectId: _pid, ...bodyWithoutProjectId } = bodyObj;
|
|
263
|
+
const loaded = loadFlow(bodyWithoutProjectId);
|
|
264
|
+
if (loaded.kind === 'err') {
|
|
265
|
+
c.status(statusFor('validation-failed') as never);
|
|
266
|
+
return c.json(
|
|
267
|
+
toWireError(
|
|
268
|
+
{
|
|
269
|
+
code: 'validation-failed',
|
|
270
|
+
message: loaded.error.message,
|
|
271
|
+
issues: toIssues(loaded.error) as unknown as Record<string, unknown>[],
|
|
272
|
+
},
|
|
273
|
+
requestId,
|
|
274
|
+
),
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const principal = c.get('principal') as Principal | undefined;
|
|
279
|
+
const creatorUserId =
|
|
280
|
+
principal?.actor.kind === 'user' ? (principal.actor.id as UserId) : undefined;
|
|
281
|
+
const outcome = await binding.publish({
|
|
282
|
+
tenantId,
|
|
283
|
+
projectId,
|
|
284
|
+
flow: loaded.value,
|
|
285
|
+
enqueueTuples: (flowId) =>
|
|
286
|
+
tuplesForCreate({ kind: 'flow', id: flowId as FlowId, tenantId, projectId }, creatorUserId),
|
|
287
|
+
});
|
|
288
|
+
if (outcome.kind === 'already-registered') {
|
|
289
|
+
c.status(statusFor('flow-already-registered') as never);
|
|
290
|
+
return c.json(
|
|
291
|
+
toWireError(
|
|
292
|
+
{
|
|
293
|
+
code: 'flow-already-registered',
|
|
294
|
+
message: `Flow "${outcome.flowId as unknown as string}" version "${outcome.version}" is already registered`,
|
|
295
|
+
flowId: outcome.flowId as unknown as string,
|
|
296
|
+
version: outcome.version,
|
|
297
|
+
},
|
|
298
|
+
requestId,
|
|
299
|
+
),
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
if (outcome.kind === 'project-not-found') {
|
|
303
|
+
// Caller supplied a `projectId` that does not resolve within
|
|
304
|
+
// this tenant. Distinct signal from `already-registered` so the
|
|
305
|
+
// client can prompt for a valid project rather than assume the
|
|
306
|
+
// version was already used. Answered as `400 bad-input`; the
|
|
307
|
+
// caller learns from the message which field was invalid.
|
|
308
|
+
c.status(statusFor('bad-input') as never);
|
|
309
|
+
return c.json(
|
|
310
|
+
toWireError(
|
|
311
|
+
{
|
|
312
|
+
code: 'bad-input',
|
|
313
|
+
message: `\`projectId\` "${outcome.projectId as unknown as string}" does not resolve to a project in this tenant`,
|
|
314
|
+
},
|
|
315
|
+
requestId,
|
|
316
|
+
),
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
c.status(201);
|
|
320
|
+
return c.json({
|
|
321
|
+
flowId: outcome.flowId as unknown as string,
|
|
322
|
+
version: outcome.version,
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// ---------- POST /:flowId/versions/:version/unregister ----------
|
|
327
|
+
r.post('/:flowId/versions/:version/unregister', async (c) => {
|
|
328
|
+
const requestId = c.get('requestId');
|
|
329
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
330
|
+
const flowId = c.req.param('flowId') as FlowId;
|
|
331
|
+
const version = c.req.param('version');
|
|
332
|
+
|
|
333
|
+
const outcome = await binding.unregister({ tenantId, flowId, version });
|
|
334
|
+
if (!outcome.unregistered) {
|
|
335
|
+
c.status(statusFor('flow-not-found') as never);
|
|
336
|
+
return c.json(
|
|
337
|
+
toWireError(
|
|
338
|
+
{
|
|
339
|
+
code: 'flow-not-found',
|
|
340
|
+
message: `No flow "${flowId as unknown as string}" at version "${version}" to unregister`,
|
|
341
|
+
flowId: flowId as unknown as string,
|
|
342
|
+
version: version,
|
|
343
|
+
},
|
|
344
|
+
requestId,
|
|
345
|
+
),
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
return c.json({
|
|
349
|
+
flowId: flowId as unknown as string,
|
|
350
|
+
version: version,
|
|
351
|
+
unregistered: true,
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// ---------- POST /:flowId/versions/:version/reinstate ----------
|
|
356
|
+
r.post('/:flowId/versions/:version/reinstate', async (c) => {
|
|
357
|
+
const requestId = c.get('requestId');
|
|
358
|
+
const tenantId = c.get('tenantId') as TenantId;
|
|
359
|
+
const flowId = c.req.param('flowId') as FlowId;
|
|
360
|
+
const version = c.req.param('version');
|
|
361
|
+
const outcome = await binding.reinstateVersion({ tenantId, flowId, version });
|
|
362
|
+
if (outcome.kind === 'not-found') {
|
|
363
|
+
c.status(statusFor('flow-not-found') as never);
|
|
364
|
+
return c.json(
|
|
365
|
+
toWireError(
|
|
366
|
+
{
|
|
367
|
+
code: 'flow-not-found',
|
|
368
|
+
message: `No flow "${flowId as unknown as string}" at version "${version}" to reinstate`,
|
|
369
|
+
flowId: flowId as unknown as string,
|
|
370
|
+
version,
|
|
371
|
+
},
|
|
372
|
+
requestId,
|
|
373
|
+
),
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
return c.json({
|
|
377
|
+
flowId: outcome.flowId as unknown as string,
|
|
378
|
+
version: outcome.version,
|
|
379
|
+
wasTombstoned: outcome.wasTombstoned,
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
return r;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function serializeGraph(g: Flow): Record<string, unknown> {
|
|
387
|
+
return {
|
|
388
|
+
id: g.id as unknown as string,
|
|
389
|
+
version: g.version,
|
|
390
|
+
...(g.name !== undefined && { name: g.name }),
|
|
391
|
+
...(g.description !== undefined && { description: g.description }),
|
|
392
|
+
nodes: g.nodes,
|
|
393
|
+
edges: g.edges,
|
|
394
|
+
...(g.maxParallelism !== undefined && { maxParallelism: g.maxParallelism }),
|
|
395
|
+
...(g.metadata !== undefined && { metadata: g.metadata }),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Normalize any `FlowError` to a flat `issues[]` list so the wire
|
|
401
|
+
* response shape is uniform. Errors that already carry an `issues`
|
|
402
|
+
* array (schema-validation-failed, loop-invalid-output-schema) pass
|
|
403
|
+
* through unchanged; the discrete errors project their structural
|
|
404
|
+
* fields into a single-element issues list keyed by the natural path.
|
|
405
|
+
*/
|
|
406
|
+
function toIssues(err: FlowError): readonly { readonly path: string; readonly message: string }[] {
|
|
407
|
+
if ('issues' in err) return err.issues;
|
|
408
|
+
const path = derivePath(err);
|
|
409
|
+
return [{ path, message: err.message }];
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function derivePath(err: FlowError): string {
|
|
413
|
+
if ('edgeId' in err && err.edgeId !== undefined) {
|
|
414
|
+
return `edges/${err.edgeId as unknown as string}`;
|
|
415
|
+
}
|
|
416
|
+
if ('nodeId' in err && err.nodeId !== undefined) {
|
|
417
|
+
return `nodes/${err.nodeId as unknown as string}`;
|
|
418
|
+
}
|
|
419
|
+
if ('loopNodeId' in err && err.loopNodeId !== undefined) {
|
|
420
|
+
return `nodes/${err.loopNodeId as unknown as string}`;
|
|
421
|
+
}
|
|
422
|
+
return '';
|
|
423
|
+
}
|