@kindgi/api 0.1.4-rc.0 → 0.1.4-rc.2

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.
Files changed (262) hide show
  1. package/dist/agent-binding.d.ts +20 -2
  2. package/dist/agent-binding.d.ts.map +1 -1
  3. package/dist/agent-pins.d.ts.map +1 -1
  4. package/dist/agent-pins.js +4 -1
  5. package/dist/agent-pins.js.map +1 -1
  6. package/dist/app.d.ts +8 -0
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +30 -5
  9. package/dist/app.js.map +1 -1
  10. package/dist/deploy-versions.d.ts +10 -5
  11. package/dist/deploy-versions.d.ts.map +1 -1
  12. package/dist/deploy-versions.js +4 -10
  13. package/dist/deploy-versions.js.map +1 -1
  14. package/dist/derive-agent-version.d.ts +9 -1
  15. package/dist/derive-agent-version.d.ts.map +1 -1
  16. package/dist/derive-agent-version.js +11 -1
  17. package/dist/derive-agent-version.js.map +1 -1
  18. package/dist/errors.d.ts.map +1 -1
  19. package/dist/errors.js +26 -0
  20. package/dist/errors.js.map +1 -1
  21. package/dist/eval-case-binding.d.ts +10 -0
  22. package/dist/eval-case-binding.d.ts.map +1 -1
  23. package/dist/eval-run-binding.d.ts +21 -3
  24. package/dist/eval-run-binding.d.ts.map +1 -1
  25. package/dist/eval-run-binding.js.map +1 -1
  26. package/dist/eval-run-dispatcher.d.ts +3 -0
  27. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  28. package/dist/eval-run-dispatcher.js.map +1 -1
  29. package/dist/flow-binding.d.ts +8 -0
  30. package/dist/flow-binding.d.ts.map +1 -1
  31. package/dist/flow-pins.d.ts +20 -7
  32. package/dist/flow-pins.d.ts.map +1 -1
  33. package/dist/flow-pins.js +36 -11
  34. package/dist/flow-pins.js.map +1 -1
  35. package/dist/gate-policy-binding.d.ts +164 -0
  36. package/dist/gate-policy-binding.d.ts.map +1 -0
  37. package/dist/gate-policy-binding.js +12 -0
  38. package/dist/gate-policy-binding.js.map +1 -0
  39. package/dist/gate.d.ts +56 -0
  40. package/dist/gate.d.ts.map +1 -0
  41. package/dist/gate.js +359 -0
  42. package/dist/gate.js.map +1 -0
  43. package/dist/guardrail-binding.d.ts +8 -0
  44. package/dist/guardrail-binding.d.ts.map +1 -1
  45. package/dist/handler-binding.d.ts +17 -2
  46. package/dist/handler-binding.d.ts.map +1 -1
  47. package/dist/index.d.ts +11 -4
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/judged-dispatcher.d.ts +20 -1
  52. package/dist/judged-dispatcher.d.ts.map +1 -1
  53. package/dist/judged-dispatcher.js +57 -7
  54. package/dist/judged-dispatcher.js.map +1 -1
  55. package/dist/judgment-binding.d.ts +38 -0
  56. package/dist/judgment-binding.d.ts.map +1 -1
  57. package/dist/judgment-binding.js +19 -0
  58. package/dist/judgment-binding.js.map +1 -1
  59. package/dist/live-version-binding.d.ts +206 -0
  60. package/dist/live-version-binding.d.ts.map +1 -0
  61. package/dist/live-version-binding.js +4 -0
  62. package/dist/live-version-binding.js.map +1 -0
  63. package/dist/middleware/authorize.d.ts.map +1 -1
  64. package/dist/middleware/authorize.js +13 -2
  65. package/dist/middleware/authorize.js.map +1 -1
  66. package/dist/middleware/project-ref.d.ts +25 -0
  67. package/dist/middleware/project-ref.d.ts.map +1 -0
  68. package/dist/middleware/project-ref.js +72 -0
  69. package/dist/middleware/project-ref.js.map +1 -0
  70. package/dist/openapi/generate.d.ts.map +1 -1
  71. package/dist/openapi/generate.js +4 -0
  72. package/dist/openapi/generate.js.map +1 -1
  73. package/dist/openapi/operations.d.ts +6 -0
  74. package/dist/openapi/operations.d.ts.map +1 -1
  75. package/dist/openapi/operations.js +524 -27
  76. package/dist/openapi/operations.js.map +1 -1
  77. package/dist/openapi/schemas.d.ts +43 -0
  78. package/dist/openapi/schemas.d.ts.map +1 -1
  79. package/dist/openapi/schemas.js +1050 -7
  80. package/dist/openapi/schemas.js.map +1 -1
  81. package/dist/publish-refused.d.ts +18 -0
  82. package/dist/publish-refused.d.ts.map +1 -0
  83. package/dist/publish-refused.js +22 -0
  84. package/dist/publish-refused.js.map +1 -0
  85. package/dist/registry-read-only.d.ts +32 -0
  86. package/dist/registry-read-only.d.ts.map +1 -0
  87. package/dist/registry-read-only.js +22 -0
  88. package/dist/registry-read-only.js.map +1 -0
  89. package/dist/retention-binding.d.ts +29 -0
  90. package/dist/retention-binding.d.ts.map +1 -1
  91. package/dist/routes/agent-releases.d.ts +40 -0
  92. package/dist/routes/agent-releases.d.ts.map +1 -0
  93. package/dist/routes/agent-releases.js +462 -0
  94. package/dist/routes/agent-releases.js.map +1 -0
  95. package/dist/routes/agents.d.ts +7 -1
  96. package/dist/routes/agents.d.ts.map +1 -1
  97. package/dist/routes/agents.js +38 -4
  98. package/dist/routes/agents.js.map +1 -1
  99. package/dist/routes/approvals.d.ts.map +1 -1
  100. package/dist/routes/approvals.js +27 -9
  101. package/dist/routes/approvals.js.map +1 -1
  102. package/dist/routes/audit.d.ts.map +1 -1
  103. package/dist/routes/audit.js +7 -0
  104. package/dist/routes/audit.js.map +1 -1
  105. package/dist/routes/auth.js +1 -1
  106. package/dist/routes/auth.js.map +1 -1
  107. package/dist/routes/blocks.d.ts.map +1 -1
  108. package/dist/routes/blocks.js +37 -12
  109. package/dist/routes/blocks.js.map +1 -1
  110. package/dist/routes/conversations.d.ts +0 -7
  111. package/dist/routes/conversations.d.ts.map +1 -1
  112. package/dist/routes/conversations.js +19 -3
  113. package/dist/routes/conversations.js.map +1 -1
  114. package/dist/routes/deployments.d.ts +6 -0
  115. package/dist/routes/deployments.d.ts.map +1 -1
  116. package/dist/routes/deployments.js +49 -5
  117. package/dist/routes/deployments.js.map +1 -1
  118. package/dist/routes/env.d.ts.map +1 -1
  119. package/dist/routes/env.js +1 -0
  120. package/dist/routes/env.js.map +1 -1
  121. package/dist/routes/eval-comparison.d.ts +4 -2
  122. package/dist/routes/eval-comparison.d.ts.map +1 -1
  123. package/dist/routes/eval-comparison.js +59 -10
  124. package/dist/routes/eval-comparison.js.map +1 -1
  125. package/dist/routes/eval-runs.d.ts +7 -1
  126. package/dist/routes/eval-runs.d.ts.map +1 -1
  127. package/dist/routes/eval-runs.js +34 -3
  128. package/dist/routes/eval-runs.js.map +1 -1
  129. package/dist/routes/eval-versions.d.ts +25 -0
  130. package/dist/routes/eval-versions.d.ts.map +1 -0
  131. package/dist/routes/eval-versions.js +66 -0
  132. package/dist/routes/eval-versions.js.map +1 -0
  133. package/dist/routes/flows.d.ts +14 -7
  134. package/dist/routes/flows.d.ts.map +1 -1
  135. package/dist/routes/flows.js +14 -8
  136. package/dist/routes/flows.js.map +1 -1
  137. package/dist/routes/gate-policies.d.ts +19 -0
  138. package/dist/routes/gate-policies.d.ts.map +1 -0
  139. package/dist/routes/gate-policies.js +191 -0
  140. package/dist/routes/gate-policies.js.map +1 -0
  141. package/dist/routes/gate-policy-spec.d.ts +17 -0
  142. package/dist/routes/gate-policy-spec.d.ts.map +1 -0
  143. package/dist/routes/gate-policy-spec.js +192 -0
  144. package/dist/routes/gate-policy-spec.js.map +1 -0
  145. package/dist/routes/gate-policy-wire.d.ts +3 -0
  146. package/dist/routes/gate-policy-wire.d.ts.map +1 -0
  147. package/dist/routes/gate-policy-wire.js +18 -0
  148. package/dist/routes/gate-policy-wire.js.map +1 -0
  149. package/dist/routes/guardrails.d.ts.map +1 -1
  150. package/dist/routes/guardrails.js +4 -0
  151. package/dist/routes/guardrails.js.map +1 -1
  152. package/dist/routes/hierarchy-errors.d.ts +21 -0
  153. package/dist/routes/hierarchy-errors.d.ts.map +1 -1
  154. package/dist/routes/hierarchy-errors.js +21 -0
  155. package/dist/routes/hierarchy-errors.js.map +1 -1
  156. package/dist/routes/judged-suites.js +7 -0
  157. package/dist/routes/judged-suites.js.map +1 -1
  158. package/dist/routes/judgments.d.ts +4 -1
  159. package/dist/routes/judgments.d.ts.map +1 -1
  160. package/dist/routes/judgments.js +92 -19
  161. package/dist/routes/judgments.js.map +1 -1
  162. package/dist/routes/live-scope-wire.d.ts +32 -0
  163. package/dist/routes/live-scope-wire.d.ts.map +1 -0
  164. package/dist/routes/live-scope-wire.js +71 -0
  165. package/dist/routes/live-scope-wire.js.map +1 -0
  166. package/dist/routes/policies.d.ts +6 -3
  167. package/dist/routes/policies.d.ts.map +1 -1
  168. package/dist/routes/policies.js +55 -3
  169. package/dist/routes/policies.js.map +1 -1
  170. package/dist/routes/projects.d.ts.map +1 -1
  171. package/dist/routes/projects.js +59 -9
  172. package/dist/routes/projects.js.map +1 -1
  173. package/dist/routes/retention.d.ts.map +1 -1
  174. package/dist/routes/retention.js +18 -2
  175. package/dist/routes/retention.js.map +1 -1
  176. package/dist/routes/reviewers.d.ts +8 -1
  177. package/dist/routes/reviewers.d.ts.map +1 -1
  178. package/dist/routes/reviewers.js +20 -3
  179. package/dist/routes/reviewers.js.map +1 -1
  180. package/dist/routes/runs.d.ts.map +1 -1
  181. package/dist/routes/runs.js +23 -13
  182. package/dist/routes/runs.js.map +1 -1
  183. package/dist/routes/secrets.d.ts.map +1 -1
  184. package/dist/routes/secrets.js +2 -0
  185. package/dist/routes/secrets.js.map +1 -1
  186. package/dist/routes/segments.d.ts +17 -0
  187. package/dist/routes/segments.d.ts.map +1 -0
  188. package/dist/routes/segments.js +68 -0
  189. package/dist/routes/segments.js.map +1 -0
  190. package/dist/routes/teams.d.ts.map +1 -1
  191. package/dist/routes/teams.js +53 -8
  192. package/dist/routes/teams.js.map +1 -1
  193. package/dist/routes/tools.d.ts.map +1 -1
  194. package/dist/routes/tools.js +4 -0
  195. package/dist/routes/tools.js.map +1 -1
  196. package/dist/routes/uuid-param.d.ts +11 -0
  197. package/dist/routes/uuid-param.d.ts.map +1 -0
  198. package/dist/routes/uuid-param.js +19 -0
  199. package/dist/routes/uuid-param.js.map +1 -0
  200. package/dist/tool-binding.d.ts +8 -0
  201. package/dist/tool-binding.d.ts.map +1 -1
  202. package/openapi.json +6484 -2402
  203. package/package.json +21 -21
  204. package/src/agent-binding.ts +21 -2
  205. package/src/agent-pins.ts +3 -1
  206. package/src/app.ts +47 -4
  207. package/src/deploy-versions.ts +12 -15
  208. package/src/derive-agent-version.ts +12 -1
  209. package/src/errors.ts +26 -0
  210. package/src/eval-case-binding.ts +7 -0
  211. package/src/eval-run-binding.ts +31 -3
  212. package/src/eval-run-dispatcher.ts +3 -0
  213. package/src/flow-binding.ts +9 -0
  214. package/src/flow-pins.ts +49 -9
  215. package/src/gate-policy-binding.ts +171 -0
  216. package/src/gate.ts +467 -0
  217. package/src/guardrail-binding.ts +9 -0
  218. package/src/handler-binding.ts +17 -2
  219. package/src/index.ts +47 -1
  220. package/src/judged-dispatcher.ts +100 -9
  221. package/src/judgment-binding.ts +62 -0
  222. package/src/live-version-binding.ts +237 -0
  223. package/src/middleware/authorize.ts +18 -2
  224. package/src/middleware/project-ref.ts +88 -0
  225. package/src/openapi/generate.ts +5 -0
  226. package/src/openapi/operations.ts +664 -27
  227. package/src/openapi/schemas.ts +1175 -33
  228. package/src/publish-refused.ts +31 -0
  229. package/src/registry-read-only.ts +43 -0
  230. package/src/retention-binding.ts +30 -0
  231. package/src/routes/agent-releases.ts +581 -0
  232. package/src/routes/agents.ts +53 -3
  233. package/src/routes/approvals.ts +36 -8
  234. package/src/routes/audit.ts +10 -0
  235. package/src/routes/auth.ts +1 -1
  236. package/src/routes/blocks.ts +39 -14
  237. package/src/routes/conversations.ts +31 -3
  238. package/src/routes/deployments.ts +75 -5
  239. package/src/routes/env.ts +1 -0
  240. package/src/routes/eval-comparison.ts +59 -11
  241. package/src/routes/eval-runs.ts +46 -3
  242. package/src/routes/eval-versions.ts +110 -0
  243. package/src/routes/flows.ts +34 -11
  244. package/src/routes/gate-policies.ts +226 -0
  245. package/src/routes/gate-policy-spec.ts +229 -0
  246. package/src/routes/gate-policy-wire.ts +20 -0
  247. package/src/routes/guardrails.ts +7 -0
  248. package/src/routes/hierarchy-errors.ts +23 -0
  249. package/src/routes/judged-suites.ts +5 -0
  250. package/src/routes/judgments.ts +107 -23
  251. package/src/routes/live-scope-wire.ts +90 -0
  252. package/src/routes/policies.ts +61 -3
  253. package/src/routes/projects.ts +72 -9
  254. package/src/routes/retention.ts +21 -2
  255. package/src/routes/reviewers.ts +23 -4
  256. package/src/routes/runs.ts +34 -20
  257. package/src/routes/secrets.ts +2 -0
  258. package/src/routes/segments.ts +75 -0
  259. package/src/routes/teams.ts +66 -8
  260. package/src/routes/tools.ts +7 -0
  261. package/src/routes/uuid-param.ts +28 -0
  262. package/src/tool-binding.ts +9 -0
@@ -0,0 +1,462 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { statusFor, toWireError } from '../errors.js';
4
+ import { evaluateGate } from '../gate.js';
5
+ import { serializeGatePolicy } from './gate-policy-wire.js';
6
+ import { liveScopeToWire, parseLiveScopeBody } from './live-scope-wire.js';
7
+ import { clampLimit } from './pagination.js';
8
+ import { parseSegmentsQuery } from './segments.js';
9
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10
+ /** The routes that change what's live: authorized as `promote` on the agent, not `admin`. */
11
+ export function isPromotionWrite(method, path) {
12
+ return method === 'POST' && /\/(promotions|live\/rollback|live\/unpin)$/.test(path);
13
+ }
14
+ /** `POST …/promotions/check` changes nothing: `read` on the agent. */
15
+ export function isPromotionCheck(method, path) {
16
+ return method === 'POST' && path.endsWith('/promotions/check');
17
+ }
18
+ /**
19
+ * Live versions of an agent per scope, and the promotions that set them
20
+ * (evals step 4):
21
+ * GET /:agentId/live the version a run would use for a project and segment path
22
+ * GET /:agentId/live-versions every pin
23
+ * POST /:agentId/promotions make a version live for a scope, through its gate
24
+ * (201 promoted, 202 waiting for approval, 422 gate-failed)
25
+ * POST /:agentId/promotions/check what the gate would say, writing nothing
26
+ * GET /:agentId/gate-policy the gate policy that applies to a scope
27
+ * GET /:agentId/promotions[/:id] the history
28
+ * POST /:agentId/live/rollback back to the scope's previous live version
29
+ * POST /:agentId/live/unpin remove the scope's pin (it falls back to the scope above)
30
+ */
31
+ export function mountAgentReleaseRoutes(r, registry, releases, deps = {}) {
32
+ r.get('/:agentId/live', async (c) => {
33
+ const requestId = c.get('requestId');
34
+ const tenantId = c.get('tenantId');
35
+ const agentId = c.req.param('agentId');
36
+ const projectId = c.req.query('projectId');
37
+ if (projectId !== undefined && !UUID_RE.test(projectId)) {
38
+ c.status(statusFor('bad-input'));
39
+ return c.json(toWireError({ code: 'bad-input', message: '`projectId` must be a project id (a UUID)' }, requestId));
40
+ }
41
+ const segments = parseSegmentsQuery(c.req.queries('segment') ?? []);
42
+ if (segments.kind === 'err') {
43
+ c.status(statusFor('bad-input'));
44
+ return c.json(toWireError({ code: 'bad-input', message: segments.message }, requestId));
45
+ }
46
+ if (segments.segments !== undefined && projectId === undefined) {
47
+ c.status(statusFor('bad-input'));
48
+ return c.json(toWireError({ code: 'bad-input', message: 'A `segment` path needs a `projectId`' }, requestId));
49
+ }
50
+ const resolved = await releases.live.resolve({
51
+ tenantId,
52
+ agentId,
53
+ ...(projectId !== undefined && { projectId: projectId }),
54
+ ...(segments.segments !== undefined && { segments: segments.segments }),
55
+ });
56
+ if (resolved !== null) {
57
+ return c.json({
58
+ agentId,
59
+ version: resolved.version,
60
+ via: 'live',
61
+ liveScope: liveScopeToWire(resolved.scope),
62
+ });
63
+ }
64
+ // Nothing pinned on the way up: what a run gets is the latest registered version.
65
+ const latest = await registry.get({ tenantId, agentId: agentId });
66
+ if (latest === null) {
67
+ c.status(statusFor('agent-not-found'));
68
+ return c.json(toWireError({ code: 'agent-not-found', message: `No agent "${agentId}" is registered` }, requestId));
69
+ }
70
+ return c.json({ agentId, version: latest.version, via: 'latest' });
71
+ });
72
+ r.get('/:agentId/live-versions', async (c) => {
73
+ const tenantId = c.get('tenantId');
74
+ const pins = await releases.live.list({ tenantId, agentId: c.req.param('agentId') });
75
+ return c.json({
76
+ data: pins.map((p) => ({
77
+ agentId: p.agentId,
78
+ scope: liveScopeToWire(p.scope),
79
+ version: p.version,
80
+ promotionId: p.promotionId,
81
+ setAt: p.setAt,
82
+ })),
83
+ });
84
+ });
85
+ r.post('/:agentId/promotions', async (c) => {
86
+ const requestId = c.get('requestId');
87
+ const parsed = await readPromotionBody(c);
88
+ if (parsed.kind === 'err')
89
+ return badInput(c, requestId, parsed.message);
90
+ const tenantId = c.get('tenantId');
91
+ const agentId = c.req.param('agentId');
92
+ const input = {
93
+ tenantId,
94
+ agentId,
95
+ version: parsed.value.version,
96
+ scope: parsed.value.scope,
97
+ requestedBy: actorOf(c),
98
+ ...(parsed.value.reason !== undefined && { reason: parsed.value.reason }),
99
+ ...(parsed.value.evalRunId !== undefined && { evalRunId: parsed.value.evalRunId }),
100
+ };
101
+ const policy = await policyFor(releases, tenantId, agentId, parsed.value.scope);
102
+ if (releases.promotions.request === undefined) {
103
+ if (policy !== null) {
104
+ c.status(statusFor('promotion-gate-unsupported'));
105
+ return c.json(toWireError({
106
+ code: 'promotion-gate-unsupported',
107
+ message: `Gate policy ${policy.id} ${policy.version} applies to this promotion, and this deployment can't record a gated promotion yet.`,
108
+ }, requestId));
109
+ }
110
+ // No gate, and a binding from before gates: promote as before.
111
+ const outcome = await releases.promotions.promote(input);
112
+ if (outcome.kind === 'err')
113
+ return failed(c, requestId, outcome.error);
114
+ c.status(201);
115
+ return c.json(serializePromotion(outcome.value));
116
+ }
117
+ const gate = await runGate(registry, releases, deps, { ...parsed.value, tenantId, agentId }, policy);
118
+ if (gate.kind === 'err')
119
+ return failed(c, requestId, gate.error);
120
+ const outcome = await releases.promotions.request({
121
+ ...input,
122
+ gate: {
123
+ policy: policy === null ? null : { id: policy.id, version: policy.version },
124
+ checks: gate.result.checks,
125
+ passed: gate.result.passed,
126
+ ...(gate.result.approval !== undefined && { approval: gate.result.approval }),
127
+ servingVersion: gate.servingVersion,
128
+ },
129
+ });
130
+ if (outcome.kind === 'err')
131
+ return failed(c, requestId, outcome.error);
132
+ const promotion = outcome.value;
133
+ if (promotion.status === 'refused') {
134
+ const checks = promotion.checks ?? gate.result.checks;
135
+ c.status(statusFor('gate-failed'));
136
+ return c.json(toWireError({
137
+ code: 'gate-failed',
138
+ message: `The gate refused ${agentId} ${parsed.value.version}: ${checks
139
+ .filter((check) => !check.passed)
140
+ .map((check) => check.message)
141
+ .join(' ')}`,
142
+ promotionId: promotion.id,
143
+ policy: promotion.policy ?? null,
144
+ checks,
145
+ }, requestId));
146
+ }
147
+ c.status(promotion.status === 'pending-approval' ? 202 : 201);
148
+ return c.json(serializePromotion(promotion));
149
+ });
150
+ r.post('/:agentId/promotions/check', async (c) => {
151
+ const requestId = c.get('requestId');
152
+ const parsed = await readPromotionBody(c);
153
+ if (parsed.kind === 'err')
154
+ return badInput(c, requestId, parsed.message);
155
+ const tenantId = c.get('tenantId');
156
+ const agentId = c.req.param('agentId');
157
+ const policy = await policyFor(releases, tenantId, agentId, parsed.value.scope);
158
+ const gate = await runGate(registry, releases, deps, { ...parsed.value, tenantId, agentId }, policy);
159
+ if (gate.kind === 'err')
160
+ return failed(c, requestId, gate.error);
161
+ const { result } = gate;
162
+ return c.json({
163
+ outcome: !result.passed
164
+ ? 'gate-failed'
165
+ : result.approval !== undefined
166
+ ? 'needs-approval'
167
+ : 'would-promote',
168
+ policy: policy === null ? null : { id: policy.id, version: policy.version },
169
+ checks: result.checks,
170
+ ...(result.approval !== undefined && { approval: result.approval }),
171
+ });
172
+ });
173
+ r.get('/:agentId/gate-policy', async (c) => {
174
+ const requestId = c.get('requestId');
175
+ const scope = scopeFromQuery((n) => c.req.query(n), c.req.queries('segment') ?? []);
176
+ if (scope.kind === 'err')
177
+ return badInput(c, requestId, scope.message);
178
+ if (scope.scope === undefined) {
179
+ return badInput(c, requestId, '`scopeKind` is required: the scope a promotion would be for');
180
+ }
181
+ const policy = await policyFor(releases, c.get('tenantId'), c.req.param('agentId'), scope.scope);
182
+ return c.json({ policy: policy === null ? null : serializeGatePolicy(policy) });
183
+ });
184
+ r.get('/:agentId/promotions', async (c) => {
185
+ const requestId = c.get('requestId');
186
+ const scope = scopeFromQuery((n) => c.req.query(n), c.req.queries('segment') ?? []);
187
+ if (scope.kind === 'err')
188
+ return badInput(c, requestId, scope.message);
189
+ const cursor = c.req.query('cursor');
190
+ const page = await releases.promotions.list({
191
+ tenantId: c.get('tenantId'),
192
+ agentId: c.req.param('agentId'),
193
+ limit: clampLimit(c.req.query('limit')),
194
+ ...(scope.scope !== undefined && { scope: scope.scope }),
195
+ ...(cursor !== undefined && cursor.length > 0 && { cursor: cursor }),
196
+ });
197
+ return c.json({
198
+ data: page.data.map(serializePromotion),
199
+ hasMore: page.nextCursor !== undefined,
200
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor }),
201
+ });
202
+ });
203
+ r.get('/:agentId/promotions/:promotionId', async (c) => {
204
+ const requestId = c.get('requestId');
205
+ const found = await releases.promotions.get(c.get('tenantId'), c.req.param('promotionId'));
206
+ if (found === null || found.agentId !== c.req.param('agentId')) {
207
+ c.status(statusFor('promotion-not-found'));
208
+ return c.json(toWireError({ code: 'promotion-not-found', message: 'No such promotion for this agent' }, requestId));
209
+ }
210
+ return c.json(serializePromotion(found));
211
+ });
212
+ r.post('/:agentId/live/rollback', async (c) => {
213
+ const requestId = c.get('requestId');
214
+ const body = await readBody(c);
215
+ if (body === undefined)
216
+ return badJson(c, requestId);
217
+ const scope = parseLiveScopeBody(body.scope);
218
+ if (scope.kind === 'err')
219
+ return badInput(c, requestId, scope.message);
220
+ if (body.toVersion !== undefined &&
221
+ (typeof body.toVersion !== 'string' || body.toVersion === '')) {
222
+ return badInput(c, requestId, '`toVersion` must be a version when supplied');
223
+ }
224
+ const text = optionalText(body, ['reason']);
225
+ if (text.kind === 'err')
226
+ return badInput(c, requestId, text.message);
227
+ const outcome = await releases.promotions.rollback({
228
+ tenantId: c.get('tenantId'),
229
+ agentId: c.req.param('agentId'),
230
+ scope: scope.scope,
231
+ requestedBy: actorOf(c),
232
+ ...(typeof body.toVersion === 'string' && { toVersion: body.toVersion }),
233
+ ...text.value,
234
+ });
235
+ if (outcome.kind === 'err')
236
+ return failed(c, requestId, outcome.error);
237
+ return c.json(serializePromotion(outcome.value));
238
+ });
239
+ r.post('/:agentId/live/unpin', async (c) => {
240
+ const requestId = c.get('requestId');
241
+ const body = await readBody(c);
242
+ if (body === undefined)
243
+ return badJson(c, requestId);
244
+ const scope = parseLiveScopeBody(body.scope);
245
+ if (scope.kind === 'err')
246
+ return badInput(c, requestId, scope.message);
247
+ const text = optionalText(body, ['reason']);
248
+ if (text.kind === 'err')
249
+ return badInput(c, requestId, text.message);
250
+ const outcome = await releases.promotions.unpin({
251
+ tenantId: c.get('tenantId'),
252
+ agentId: c.req.param('agentId'),
253
+ scope: scope.scope,
254
+ requestedBy: actorOf(c),
255
+ ...text.value,
256
+ });
257
+ if (outcome.kind === 'err')
258
+ return failed(c, requestId, outcome.error);
259
+ return c.json(serializePromotion(outcome.value));
260
+ });
261
+ }
262
+ async function readBody(c) {
263
+ try {
264
+ const body = await c.req.json();
265
+ return body !== null && typeof body === 'object' && !Array.isArray(body)
266
+ ? body
267
+ : undefined;
268
+ }
269
+ catch {
270
+ return undefined;
271
+ }
272
+ }
273
+ function badJson(c, requestId) {
274
+ return badInput(c, requestId, 'Request body must be a JSON object');
275
+ }
276
+ function badInput(c, requestId, message) {
277
+ c.status(statusFor('bad-input'));
278
+ return c.json(toWireError({ code: 'bad-input', message }, requestId));
279
+ }
280
+ function failed(c, requestId, error) {
281
+ c.status(statusFor(error.code));
282
+ return c.json(toWireError(error, requestId));
283
+ }
284
+ /** Optional short strings (`reason`, `evalRunId`): absent, or a non-empty string. */
285
+ function optionalText(body, fields) {
286
+ const value = {};
287
+ for (const field of fields) {
288
+ const v = body[field];
289
+ if (v === undefined)
290
+ continue;
291
+ if (typeof v !== 'string' || v.trim() === '' || v.length > 2000) {
292
+ return { kind: 'err', message: `\`${field}\` must be a non-empty string when supplied` };
293
+ }
294
+ value[field] = v;
295
+ }
296
+ return { kind: 'ok', value };
297
+ }
298
+ /** The promotion body: `{version, scope, evalRunId?, reason?}`. */
299
+ async function readPromotionBody(c) {
300
+ const body = await readBody(c);
301
+ if (body === undefined)
302
+ return { kind: 'err', message: 'Request body must be a JSON object' };
303
+ const scope = parseLiveScopeBody(body.scope);
304
+ if (scope.kind === 'err')
305
+ return scope;
306
+ if (typeof body.version !== 'string' || body.version.length === 0) {
307
+ return { kind: 'err', message: '`version` is required: the agent version to make live' };
308
+ }
309
+ const text = optionalText(body, ['reason', 'evalRunId']);
310
+ if (text.kind === 'err')
311
+ return text;
312
+ return {
313
+ kind: 'ok',
314
+ value: { version: body.version, scope: scope.scope, ...text.value },
315
+ };
316
+ }
317
+ /** The gate policy for a promotion of `agentId` for `scope`; `null` when none applies. */
318
+ async function policyFor(releases, tenantId, agentId, scope) {
319
+ return releases.gatePolicies === undefined
320
+ ? null
321
+ : releases.gatePolicies.resolve({ tenantId, agentId, scope });
322
+ }
323
+ /** The scope's coordinates, as a run in it would resolve its version. */
324
+ function coordinatesOf(scope) {
325
+ switch (scope.kind) {
326
+ case 'tenant':
327
+ return {};
328
+ case 'org':
329
+ return { orgId: scope.orgId };
330
+ case 'project':
331
+ return { projectId: scope.projectId };
332
+ case 'segment':
333
+ return { projectId: scope.projectId, segments: scope.path };
334
+ }
335
+ }
336
+ /** A finished comparison's summary, or `null` for any other eval run. */
337
+ function summaryOf(run) {
338
+ const summary = run.result?.summary;
339
+ return run.kind === 'judged' && summary !== null && typeof summary === 'object'
340
+ ? summary
341
+ : null;
342
+ }
343
+ /**
344
+ * The gate for a promotion request: what serves the scope now, the
345
+ * comparison it names, and the policy's checks against them. With no
346
+ * policy there's nothing to check.
347
+ */
348
+ async function runGate(registry, releases, deps, req, policy) {
349
+ const { tenantId, agentId } = req;
350
+ const err = (code, message) => ({
351
+ kind: 'err',
352
+ error: { code, message },
353
+ });
354
+ const promoted = await registry.getVersion({
355
+ tenantId,
356
+ agentId: agentId,
357
+ version: req.version,
358
+ });
359
+ if (promoted === null || promoted.unregisteredAt !== undefined) {
360
+ return err('agent-version-not-found', `${agentId} has no active version ${req.version}`);
361
+ }
362
+ const live = await releases.live.resolve({ tenantId, agentId, ...coordinatesOf(req.scope) });
363
+ let servingVersion = live?.version;
364
+ if (servingVersion === undefined) {
365
+ const latest = await registry.get({ tenantId, agentId: agentId });
366
+ if (latest === null)
367
+ return err('agent-not-found', `No agent "${agentId}" is registered`);
368
+ servingVersion = latest.version;
369
+ }
370
+ if (policy === null)
371
+ return { kind: 'ok', result: { checks: [], passed: true }, servingVersion };
372
+ let summary = null;
373
+ if (req.evalRunId !== undefined) {
374
+ const run = deps.evalRuns === undefined
375
+ ? null
376
+ : await deps.evalRuns.get({ tenantId, runId: req.evalRunId });
377
+ if (run === null)
378
+ return err('eval-run-not-found', `No eval run ${req.evalRunId}`);
379
+ summary = summaryOf(run);
380
+ if (summary === null) {
381
+ return err('bad-input', `Eval run ${req.evalRunId} isn't a finished comparison: it has no comparison summary`);
382
+ }
383
+ }
384
+ let summaryProjectOrgId;
385
+ const judgedIn = summary?.scope.projectId;
386
+ if (req.scope.kind === 'org' && judgedIn !== undefined && deps.projects !== undefined) {
387
+ const project = await deps.projects.get(tenantId, judgedIn);
388
+ summaryProjectOrgId = project?.orgId;
389
+ }
390
+ const result = evaluateGate({
391
+ spec: policy.spec,
392
+ promotion: {
393
+ agentId,
394
+ version: req.version,
395
+ pinsDigest: promoted.pinsDigest ?? null,
396
+ scope: req.scope,
397
+ },
398
+ summary,
399
+ servingVersion,
400
+ ...(summaryProjectOrgId !== undefined && { summaryProjectOrgId }),
401
+ now: new Date(),
402
+ });
403
+ return { kind: 'ok', result, servingVersion };
404
+ }
405
+ /** Who asked, from the request's principal. */
406
+ function actorOf(c) {
407
+ const actor = c.get('principal')?.actor;
408
+ if (actor === undefined)
409
+ return { kind: 'service', id: 'unknown' };
410
+ return { kind: actor.kind === 'user' ? 'user' : 'service', id: actor.id };
411
+ }
412
+ /** `?scopeKind=tenant|org|project|segment&scopeId=…&segment=key:value` for the history filter. */
413
+ export function scopeFromQuery(query, segmentValues) {
414
+ const kind = query('scopeKind');
415
+ const id = query('scopeId');
416
+ if (kind === undefined || kind === '') {
417
+ return id === undefined
418
+ ? { kind: 'ok' }
419
+ : { kind: 'err', message: '`scopeId` needs `scopeKind`' };
420
+ }
421
+ if (kind === 'tenant')
422
+ return { kind: 'ok', scope: { kind: 'tenant' } };
423
+ if (id === undefined || !UUID_RE.test(id)) {
424
+ return { kind: 'err', message: '`scopeId` must be an org or project id (a UUID)' };
425
+ }
426
+ if (kind === 'org')
427
+ return { kind: 'ok', scope: { kind: 'org', orgId: id } };
428
+ if (kind === 'project')
429
+ return { kind: 'ok', scope: { kind: 'project', projectId: id } };
430
+ if (kind === 'segment') {
431
+ const path = parseSegmentsQuery(segmentValues);
432
+ if (path.kind === 'err')
433
+ return path;
434
+ if (path.segments === undefined)
435
+ return { kind: 'err', message: 'A segment scope needs `segment`' };
436
+ return {
437
+ kind: 'ok',
438
+ scope: { kind: 'segment', projectId: id, path: path.segments },
439
+ };
440
+ }
441
+ return { kind: 'err', message: '`scopeKind` must be one of tenant, org, project, segment' };
442
+ }
443
+ export function serializePromotion(p) {
444
+ return {
445
+ id: p.id,
446
+ agentId: p.agentId,
447
+ scope: liveScopeToWire(p.scope),
448
+ action: p.action,
449
+ fromVersion: p.fromVersion,
450
+ toVersion: p.toVersion,
451
+ requestedBy: p.requestedBy,
452
+ ...(p.reason !== undefined && { reason: p.reason }),
453
+ ...(p.evalRunId !== undefined && { evalRunId: p.evalRunId }),
454
+ createdAt: p.createdAt,
455
+ ...(p.status !== undefined && { status: p.status }),
456
+ ...(p.policy !== undefined && { policy: p.policy }),
457
+ ...(p.checks !== undefined && { checks: p.checks }),
458
+ ...(p.approvalId !== undefined && { approvalId: p.approvalId }),
459
+ ...(p.resolvedAt !== undefined && { resolvedAt: p.resolvedAt }),
460
+ };
461
+ }
462
+ //# sourceMappingURL=agent-releases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-releases.js","sourceRoot":"","sources":["../../src/routes/agent-releases.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
1
  import { Hono } from 'hono';
2
2
  import type { AgentRegistryBinding } from '../agent-binding.js';
3
3
  import type { BlockRegistryBinding } from '../block-binding.js';
4
+ import type { AgentReleaseBindings } from '../live-version-binding.js';
4
5
  import type { Authorizer } from '../middleware/authorize.js';
5
6
  import type { ToolRegistryBinding } from '../tool-binding.js';
6
7
  import type { AppEnv } from '../types.js';
8
+ import { type AgentReleaseGateDeps } from './agent-releases.js';
7
9
  /**
8
10
  * Agents resource routes.
9
11
  *
@@ -21,5 +23,9 @@ import type { AppEnv } from '../types.js';
21
23
  * matches no published version refuses the publish. Without it,
22
24
  * versions carry no pins and resolve their ranges per run.
23
25
  */
24
- export declare function agentsRouter(binding: AgentRegistryBinding, authorizer?: Authorizer, toolRegistry?: ToolRegistryBinding, blockRegistry?: BlockRegistryBinding): Hono<AppEnv>;
26
+ export declare function agentsRouter(binding: AgentRegistryBinding, authorizer?: Authorizer, toolRegistry?: ToolRegistryBinding, blockRegistry?: BlockRegistryBinding,
27
+ /** Live versions per scope and promotions (evals step 4); absent → those routes aren't mounted. */
28
+ releases?: AgentReleaseBindings,
29
+ /** What a promotion's gate reads besides the releases (evals step 4b). */
30
+ gateDeps?: AgentReleaseGateDeps): Hono<AppEnv>;
25
31
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAC;AAY1C,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAEpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAQhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,oBAAoB,EAC7B,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE,mBAAmB,EAClC,aAAa,CAAC,EAAE,oBAAoB,GACnC,IAAI,CAAC,MAAM,CAAC,CAgbd"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,IAAI,EAAE,MAAM,MAAM,CAAC;AAY1C,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAEpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAQhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,KAAK,oBAAoB,EAI1B,MAAM,qBAAqB,CAAC;AAK7B;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,oBAAoB,EAC7B,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE,mBAAmB,EAClC,aAAa,CAAC,EAAE,oBAAoB;AACpC,mGAAmG;AACnG,QAAQ,CAAC,EAAE,oBAAoB;AAC/B,0EAA0E;AAC1E,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,IAAI,CAAC,MAAM,CAAC,CAmdd"}
@@ -6,6 +6,9 @@ import { ref, tuplesForCreate } from '@kindgi/authz';
6
6
  import { resolveAgentPins } from '../agent-pins.js';
7
7
  import { deriveAgentVersion, nextFreeAgentVersion, } from '../derive-agent-version.js';
8
8
  import { statusFor, toWireError } from '../errors.js';
9
+ import { refuseWritesWhenReadOnly } from '../registry-read-only.js';
10
+ import { isPromotionCheck, isPromotionWrite, mountAgentReleaseRoutes, } from './agent-releases.js';
11
+ import { liveScopeToWire } from './live-scope-wire.js';
9
12
  import { clampLimit } from './pagination.js';
10
13
  import { parseScopeParams } from './scope-params.js';
11
14
  /**
@@ -25,8 +28,15 @@ import { parseScopeParams } from './scope-params.js';
25
28
  * matches no published version refuses the publish. Without it,
26
29
  * versions carry no pins and resolve their ranges per run.
27
30
  */
28
- export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
31
+ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry,
32
+ /** Live versions per scope and promotions (evals step 4); absent → those routes aren't mounted. */
33
+ releases,
34
+ /** What a promotion's gate reads besides the releases (evals step 4b). */
35
+ gateDeps) {
29
36
  const r = new Hono();
37
+ // A read-only registry (under `kindgi dev`, the pack's files) refuses
38
+ // every write before anything else runs.
39
+ r.use('*', refuseWritesWhenReadOnly(() => binding.readOnly));
30
40
  // Authorization — check the resource directly (ref('agent', businessId));
31
41
  // permissions cascade from the parent project because the
32
42
  // AgentRegistryBinding's `publish` writes the `agent:X#parent@project:Y`
@@ -37,6 +47,9 @@ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
37
47
  // POST /:agentId/versions → publish on the agent (derive)
38
48
  // POST /:agentId/versions/:version/unregister → admin on the agent
39
49
  // POST /:agentId/versions/:version/reinstate → admin on the agent
50
+ // POST /:agentId/promotions, /live/rollback, /live/unpin → promote on the agent
51
+ // POST /:agentId/promotions/check → read on the agent (changes nothing)
52
+ // GET /:agentId/live, /live-versions, /promotions[/…] → read on the agent
40
53
  // GET / (list) → tenant-scoped fetch;
41
54
  // with a project scope
42
55
  // (?scopeKind=project&scopeId=),
@@ -78,8 +91,15 @@ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
78
91
  });
79
92
  r.use('/:agentId/*', async (c, next) => {
80
93
  // Deriving a version (POST …/versions) is `publish` on the agent;
81
- // unregister and reinstate are `admin`.
82
- const action = c.req.method === 'GET' ? 'read' : c.req.path.endsWith('/versions') ? 'publish' : 'admin';
94
+ // changing what's live is its own permission (`promote`, granted to
95
+ // the agent's admins); unregister and reinstate are `admin`.
96
+ const action = c.req.method === 'GET' || isPromotionCheck(c.req.method, c.req.path)
97
+ ? 'read'
98
+ : isPromotionWrite(c.req.method, c.req.path)
99
+ ? 'promote'
100
+ : c.req.path.endsWith('/versions')
101
+ ? 'publish'
102
+ : 'admin';
83
103
  const agentId = c.req.param('agentId') ?? '';
84
104
  const mw = authorizer.authorize(action, () => ref('agent', agentId));
85
105
  return mw(c, next);
@@ -250,7 +270,7 @@ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
250
270
  c.status(statusFor('invalid-agent'));
251
271
  return c.json(toWireError({
252
272
  code: 'validation-failed',
253
- message: `Agent "${defined.value.id}" uses tool versions that aren't published (${resolved.issues.length} issue${resolved.issues.length === 1 ? '' : 's'})`,
273
+ message: `Agent "${defined.value.id}" uses tool or data-block versions it can't pin (${resolved.issues.length} issue${resolved.issues.length === 1 ? '' : 's'})`,
254
274
  issues: resolved.issues,
255
275
  }, requestId));
256
276
  }
@@ -328,6 +348,16 @@ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
328
348
  const agentId = c.req.param('agentId');
329
349
  const version = c.req.param('version');
330
350
  const outcome = await binding.unregister({ tenantId, agentId, version });
351
+ if (!outcome.unregistered && outcome.live !== undefined && outcome.live.length > 0) {
352
+ c.status(statusFor('agent-version-live'));
353
+ return c.json(toWireError({
354
+ code: 'agent-version-live',
355
+ message: `${agentId} ${version} is live in ${outcome.live.length === 1 ? 'a scope' : `${outcome.live.length} scopes`}: roll back, unpin, or promote another version there first, then unregister it.`,
356
+ agentId: agentId,
357
+ version: version,
358
+ scopes: outcome.live.map(liveScopeToWire),
359
+ }, requestId));
360
+ }
331
361
  if (!outcome.unregistered) {
332
362
  c.status(statusFor('agent-not-found'));
333
363
  return c.json(toWireError({
@@ -370,6 +400,8 @@ export function agentsRouter(binding, authorizer, toolRegistry, blockRegistry) {
370
400
  wasTombstoned: outcome.wasTombstoned,
371
401
  });
372
402
  });
403
+ if (releases !== undefined)
404
+ mountAgentReleaseRoutes(r, binding, releases, gateDeps);
373
405
  return r;
374
406
  }
375
407
  /**
@@ -450,6 +482,8 @@ function derived(c, agentId, from, outcome) {
450
482
  case 'ok':
451
483
  c.status(201);
452
484
  return c.json(serializeAgent(outcome.agent));
485
+ case 'reused':
486
+ return c.json(serializeAgent(outcome.agent));
453
487
  case 'not-found':
454
488
  return fail('agent-not-found', {
455
489
  code: 'agent-not-found',