@shipfox/api-runners 9.3.0 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +46 -0
  3. package/dist/config.js +1 -1
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/runner-activation.d.ts +6 -0
  6. package/dist/core/runner-activation.d.ts.map +1 -1
  7. package/dist/core/runner-activation.js +20 -19
  8. package/dist/core/runner-activation.js.map +1 -1
  9. package/dist/core/runner-control-sessions.d.ts +2 -1
  10. package/dist/core/runner-control-sessions.d.ts.map +1 -1
  11. package/dist/core/runner-control-sessions.js +65 -19
  12. package/dist/core/runner-control-sessions.js.map +1 -1
  13. package/dist/db/db.d.ts +34 -0
  14. package/dist/db/db.d.ts.map +1 -1
  15. package/dist/db/index.d.ts +1 -1
  16. package/dist/db/index.d.ts.map +1 -1
  17. package/dist/db/index.js +1 -1
  18. package/dist/db/index.js.map +1 -1
  19. package/dist/db/job-executions.d.ts +7 -0
  20. package/dist/db/job-executions.d.ts.map +1 -1
  21. package/dist/db/job-executions.js +25 -0
  22. package/dist/db/job-executions.js.map +1 -1
  23. package/dist/db/runner-assignments.d.ts +6 -0
  24. package/dist/db/runner-assignments.d.ts.map +1 -1
  25. package/dist/db/runner-assignments.js +57 -42
  26. package/dist/db/runner-assignments.js.map +1 -1
  27. package/dist/db/runner-instances.d.ts.map +1 -1
  28. package/dist/db/runner-instances.js +64 -19
  29. package/dist/db/runner-instances.js.map +1 -1
  30. package/dist/db/schema/runner-instances.d.ts +17 -0
  31. package/dist/db/schema/runner-instances.d.ts.map +1 -1
  32. package/dist/db/schema/runner-instances.js +3 -0
  33. package/dist/db/schema/runner-instances.js.map +1 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/presentation/inter-module.d.ts.map +1 -1
  39. package/dist/presentation/inter-module.js +7 -2
  40. package/dist/presentation/inter-module.js.map +1 -1
  41. package/dist/presentation/routes/runner-enrollment.d.ts +9 -0
  42. package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -1
  43. package/dist/presentation/routes/runner-enrollment.js +36 -23
  44. package/dist/presentation/routes/runner-enrollment.js.map +1 -1
  45. package/dist/tsconfig.test.tsbuildinfo +1 -1
  46. package/drizzle/0001_intended_reservation.sql +3 -0
  47. package/drizzle/meta/0001_snapshot.json +2093 -0
  48. package/drizzle/meta/_journal.json +7 -0
  49. package/package.json +7 -7
  50. package/src/config.test.ts +11 -0
  51. package/src/config.ts +1 -1
  52. package/src/core/runner-activation.ts +48 -38
  53. package/src/core/runner-control-sessions.ts +115 -33
  54. package/src/db/index.ts +1 -0
  55. package/src/db/job-executions.ts +28 -0
  56. package/src/db/runner-assignments.test.ts +81 -0
  57. package/src/db/runner-assignments.ts +134 -86
  58. package/src/db/runner-instances.test.ts +182 -0
  59. package/src/db/runner-instances.ts +123 -28
  60. package/src/db/schema/runner-instances.ts +9 -0
  61. package/src/index.ts +1 -0
  62. package/src/presentation/inter-module.ts +4 -0
  63. package/src/presentation/routes/poll-demand.test.ts +2 -2
  64. package/src/presentation/routes/runner-enrollment.test.ts +144 -1
  65. package/src/presentation/routes/runner-enrollment.ts +40 -20
  66. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {runnersInterModuleContract} from '@shipfox/api-runners-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {EmptyRequiredLabelsError} from '#core/errors.js';\nimport {getEffectiveRunnerToolCapabilities} from '#core/runner-tool-capabilities.js';\nimport {\n cancelRunnerJobs,\n enqueueJobExecution,\n isJobLeaseActive,\n releaseJobExecution,\n} from '#db/job-executions.js';\n\nexport function createRunnersInterModulePresentation(): InterModulePresentation<\n typeof runnersInterModuleContract\n> {\n return defineInterModulePresentation(runnersInterModuleContract, {\n enqueueJobExecution: async (input) => {\n try {\n await enqueueJobExecution(input);\n return {};\n } catch (error) {\n throw toEnqueueJobExecutionKnownError(error);\n }\n },\n releaseJobExecution: async (input) => {\n await releaseJobExecution(input);\n return {};\n },\n cancelJobs: async (input) => {\n await cancelRunnerJobs(input);\n return {};\n },\n getLeaseState: async (input) => ({active: await isJobLeaseActive(input)}),\n getEffectiveRunnerToolCapabilities: async (input) => {\n const result = await getEffectiveRunnerToolCapabilities(input);\n return {capabilities: result.capabilities, reportFresh: result.reportFresh};\n },\n });\n}\n\nexport function toEnqueueJobExecutionKnownError(error: unknown): unknown {\n if (error instanceof EmptyRequiredLabelsError) {\n return createInterModuleKnownError(\n runnersInterModuleContract.methods.enqueueJobExecution,\n 'empty-required-labels',\n {},\n );\n }\n return error;\n}\n"],"names":["runnersInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","EmptyRequiredLabelsError","getEffectiveRunnerToolCapabilities","cancelRunnerJobs","enqueueJobExecution","isJobLeaseActive","releaseJobExecution","createRunnersInterModulePresentation","input","error","toEnqueueJobExecutionKnownError","cancelJobs","getLeaseState","active","result","capabilities","reportFresh","methods"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,wCAAwC;AACjF,SACEC,2BAA2B,EAC3BC,6BAA6B,QAExB,wBAAwB;AAC/B,SAAQC,wBAAwB,QAAO,kBAAkB;AACzD,SAAQC,kCAAkC,QAAO,oCAAoC;AACrF,SACEC,gBAAgB,EAChBC,mBAAmB,EACnBC,gBAAgB,EAChBC,mBAAmB,QACd,wBAAwB;AAE/B,OAAO,SAASC;IAGd,OAAOP,8BAA8BF,4BAA4B;QAC/DM,qBAAqB,OAAOI;YAC1B,IAAI;gBACF,MAAMJ,oBAAoBI;gBAC1B,OAAO,CAAC;YACV,EAAE,OAAOC,OAAO;gBACd,MAAMC,gCAAgCD;YACxC;QACF;QACAH,qBAAqB,OAAOE;YAC1B,MAAMF,oBAAoBE;YAC1B,OAAO,CAAC;QACV;QACAG,YAAY,OAAOH;YACjB,MAAML,iBAAiBK;YACvB,OAAO,CAAC;QACV;QACAI,eAAe,OAAOJ,QAAW,CAAA;gBAACK,QAAQ,MAAMR,iBAAiBG;YAAM,CAAA;QACvEN,oCAAoC,OAAOM;YACzC,MAAMM,SAAS,MAAMZ,mCAAmCM;YACxD,OAAO;gBAACO,cAAcD,OAAOC,YAAY;gBAAEC,aAAaF,OAAOE,WAAW;YAAA;QAC5E;IACF;AACF;AAEA,OAAO,SAASN,gCAAgCD,KAAc;IAC5D,IAAIA,iBAAiBR,0BAA0B;QAC7C,OAAOF,4BACLD,2BAA2BmB,OAAO,CAACb,mBAAmB,EACtD,yBACA,CAAC;IAEL;IACA,OAAOK;AACT"}
1
+ {"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {runnersInterModuleContract} from '@shipfox/api-runners-dto/inter-module';\nimport {\n createInterModuleKnownError,\n defineInterModulePresentation,\n type InterModulePresentation,\n} from '@shipfox/inter-module';\nimport {EmptyRequiredLabelsError} from '#core/errors.js';\nimport {getEffectiveRunnerToolCapabilities} from '#core/runner-tool-capabilities.js';\nimport {\n cancelRunnerJobs,\n enqueueJobExecution,\n getWorkspaceJobCounts,\n isJobLeaseActive,\n releaseJobExecution,\n} from '#db/job-executions.js';\n\nexport function createRunnersInterModulePresentation(): InterModulePresentation<\n typeof runnersInterModuleContract\n> {\n return defineInterModulePresentation(runnersInterModuleContract, {\n enqueueJobExecution: async (input) => {\n try {\n await enqueueJobExecution(input);\n return {};\n } catch (error) {\n throw toEnqueueJobExecutionKnownError(error);\n }\n },\n releaseJobExecution: async (input) => {\n await releaseJobExecution(input);\n return {};\n },\n cancelJobs: async (input) => {\n await cancelRunnerJobs(input);\n return {};\n },\n getLeaseState: async (input) => ({active: await isJobLeaseActive(input)}),\n getEffectiveRunnerToolCapabilities: async (input) => {\n const result = await getEffectiveRunnerToolCapabilities(input);\n return {capabilities: result.capabilities, reportFresh: result.reportFresh};\n },\n getWorkspaceJobCounts: async ({workspaceIds}) => ({\n counts: await getWorkspaceJobCounts({workspaceIds}),\n }),\n });\n}\n\nexport function toEnqueueJobExecutionKnownError(error: unknown): unknown {\n if (error instanceof EmptyRequiredLabelsError) {\n return createInterModuleKnownError(\n runnersInterModuleContract.methods.enqueueJobExecution,\n 'empty-required-labels',\n {},\n );\n }\n return error;\n}\n"],"names":["runnersInterModuleContract","createInterModuleKnownError","defineInterModulePresentation","EmptyRequiredLabelsError","getEffectiveRunnerToolCapabilities","cancelRunnerJobs","enqueueJobExecution","getWorkspaceJobCounts","isJobLeaseActive","releaseJobExecution","createRunnersInterModulePresentation","input","error","toEnqueueJobExecutionKnownError","cancelJobs","getLeaseState","active","result","capabilities","reportFresh","workspaceIds","counts","methods"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,wCAAwC;AACjF,SACEC,2BAA2B,EAC3BC,6BAA6B,QAExB,wBAAwB;AAC/B,SAAQC,wBAAwB,QAAO,kBAAkB;AACzD,SAAQC,kCAAkC,QAAO,oCAAoC;AACrF,SACEC,gBAAgB,EAChBC,mBAAmB,EACnBC,qBAAqB,EACrBC,gBAAgB,EAChBC,mBAAmB,QACd,wBAAwB;AAE/B,OAAO,SAASC;IAGd,OAAOR,8BAA8BF,4BAA4B;QAC/DM,qBAAqB,OAAOK;YAC1B,IAAI;gBACF,MAAML,oBAAoBK;gBAC1B,OAAO,CAAC;YACV,EAAE,OAAOC,OAAO;gBACd,MAAMC,gCAAgCD;YACxC;QACF;QACAH,qBAAqB,OAAOE;YAC1B,MAAMF,oBAAoBE;YAC1B,OAAO,CAAC;QACV;QACAG,YAAY,OAAOH;YACjB,MAAMN,iBAAiBM;YACvB,OAAO,CAAC;QACV;QACAI,eAAe,OAAOJ,QAAW,CAAA;gBAACK,QAAQ,MAAMR,iBAAiBG;YAAM,CAAA;QACvEP,oCAAoC,OAAOO;YACzC,MAAMM,SAAS,MAAMb,mCAAmCO;YACxD,OAAO;gBAACO,cAAcD,OAAOC,YAAY;gBAAEC,aAAaF,OAAOE,WAAW;YAAA;QAC5E;QACAZ,uBAAuB,OAAO,EAACa,YAAY,EAAC,GAAM,CAAA;gBAChDC,QAAQ,MAAMd,sBAAsB;oBAACa;gBAAY;YACnD,CAAA;IACF;AACF;AAEA,OAAO,SAASP,gCAAgCD,KAAc;IAC5D,IAAIA,iBAAiBT,0BAA0B;QAC7C,OAAOF,4BACLD,2BAA2BsB,OAAO,CAAChB,mBAAmB,EACtD,yBACA,CAAC;IAEL;IACA,OAAOM;AACT"}
@@ -4,5 +4,14 @@ export declare const exchangeRunnerBootstrapRoute: import("@shipfox/node-fastify
4
4
  export declare const enrollRunnerRoute: import("@shipfox/node-fastify").RouteDefinition;
5
5
  export declare const attachRunnerControlProviderIdRoute: import("@shipfox/node-fastify").RouteDefinition;
6
6
  export declare const runnerControlHeartbeatRoute: import("@shipfox/node-fastify").RouteDefinition;
7
+ type RunnerAssignmentPollParams = {
8
+ deadline: number;
9
+ intervalMs: number;
10
+ signal: AbortSignal;
11
+ getAssignment: () => Promise<unknown | null>;
12
+ issueActivationToken: () => Promise<string | null>;
13
+ };
14
+ export declare function pollForRunnerActivationToken(params: RunnerAssignmentPollParams): Promise<string | null>;
7
15
  export declare const runnerAssignmentPollRoute: import("@shipfox/node-fastify").RouteDefinition;
16
+ export {};
8
17
  //# sourceMappingURL=runner-enrollment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner-enrollment.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/runner-enrollment.ts"],"names":[],"mappings":"AA+BA,eAAO,MAAM,0BAA0B,iDA0BrC,CAAC;AAEH,eAAO,MAAM,mCAAmC,iDAmB9C,CAAC;AAEH,eAAO,MAAM,4BAA4B,iDA2BvC,CAAC;AAEH,eAAO,MAAM,iBAAiB,iDAuB5B,CAAC;AAEH,eAAO,MAAM,kCAAkC,iDAkB7C,CAAC;AAEH,eAAO,MAAM,2BAA2B,iDAYtC,CAAC;AAEH,eAAO,MAAM,yBAAyB,iDA2BpC,CAAC"}
1
+ {"version":3,"file":"runner-enrollment.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/runner-enrollment.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,0BAA0B,iDA2BrC,CAAC;AAEH,eAAO,MAAM,mCAAmC,iDAmB9C,CAAC;AAEH,eAAO,MAAM,4BAA4B,iDA2BvC,CAAC;AAEH,eAAO,MAAM,iBAAiB,iDAuB5B,CAAC;AAEH,eAAO,MAAM,kCAAkC,iDAkB7C,CAAC;AAEH,eAAO,MAAM,2BAA2B,iDAYtC,CAAC;AAEH,KAAK,0BAA0B,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC7C,oBAAoB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpD,CAAC;AACF,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AACD,eAAO,MAAM,yBAAyB,iDAwBpC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { requireProvisionerContext, requireRunnerControlSessionContext } from '@shipfox/api-auth-context';
2
- import { attachRunnerControlProviderIdBodySchema, createRunnerInstancesBodySchema, createRunnerInstancesResponseSchema, runnerAssignmentPollResponseSchema, runnerBootstrapExchangeBodySchema, runnerBootstrapExchangeResponseSchema, runnerControlHeartbeatResponseSchema, runnerEnrollmentBodySchema } from '@shipfox/api-runners-dto';
2
+ import { attachRunnerControlProviderIdBodySchema, createRunnerInstancesBodySchema, createRunnerInstancesResponseSchema, runnerAssignmentPollResponseSchema, runnerBootstrapExchangeBodySchema, runnerBootstrapExchangeResponseSchema, runnerControlHeartbeatResponseSchema, runnerEnrollmentBodySchema, runnerEnrollmentResponseSchema } from '@shipfox/api-runners-dto';
3
3
  import { ClientError, defineRoute } from '@shipfox/node-fastify';
4
4
  import { z } from 'zod';
5
5
  import { config } from '#config.js';
@@ -25,9 +25,14 @@ export const createRunnerInstancesRoute = defineRoute({
25
25
  ...request.body.provider_kind ? {
26
26
  providerKind: request.body.provider_kind
27
27
  } : {},
28
- runnerInstances: request.body.runner_instances.map((runner)=>runner.template_key ? {
29
- templateKey: runner.template_key
30
- } : {}),
28
+ runnerInstances: request.body.runner_instances.map((runner)=>({
29
+ ...runner.template_key ? {
30
+ templateKey: runner.template_key
31
+ } : {},
32
+ ...runner.reservation_id ? {
33
+ reservationId: runner.reservation_id
34
+ } : {}
35
+ })),
31
36
  ttlSeconds: config.RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS
32
37
  });
33
38
  return {
@@ -105,7 +110,7 @@ export const enrollRunnerRoute = defineRoute({
105
110
  schema: {
106
111
  body: runnerEnrollmentBodySchema,
107
112
  response: {
108
- 204: z.null()
113
+ 200: runnerEnrollmentResponseSchema
109
114
  }
110
115
  },
111
116
  preHandler: authenticateRunnerControlSession,
@@ -115,9 +120,9 @@ export const enrollRunnerRoute = defineRoute({
115
120
  });
116
121
  throw error;
117
122
  },
118
- handler: async (request, reply)=>{
123
+ handler: async (request)=>{
119
124
  const session = requireRunnerControlSessionContext(request);
120
- await enrollRunnerControlSession({
125
+ const activationToken = await enrollRunnerControlSession({
121
126
  runnerInstanceId: session.runnerInstanceId,
122
127
  provisionerId: session.provisionerId,
123
128
  labels: request.body.labels,
@@ -127,7 +132,9 @@ export const enrollRunnerRoute = defineRoute({
127
132
  providerKind: request.body.provider_kind,
128
133
  protocolVersion: request.body.protocol_version
129
134
  });
130
- return await reply.code(204).send();
135
+ return {
136
+ activation_token: activationToken
137
+ };
131
138
  }
132
139
  });
133
140
  export const attachRunnerControlProviderIdRoute = defineRoute({
@@ -172,6 +179,18 @@ export const runnerControlHeartbeatRoute = defineRoute({
172
179
  };
173
180
  }
174
181
  });
182
+ export async function pollForRunnerActivationToken(params) {
183
+ while(Date.now() <= params.deadline){
184
+ if (params.signal.aborted) return null;
185
+ const assignment = await params.getAssignment();
186
+ if (assignment) {
187
+ const activationToken = await params.issueActivationToken();
188
+ if (activationToken) return activationToken;
189
+ }
190
+ await new Promise((resolve)=>setTimeout(resolve, params.intervalMs));
191
+ }
192
+ return null;
193
+ }
175
194
  export const runnerAssignmentPollRoute = defineRoute({
176
195
  method: 'GET',
177
196
  path: '/assignment',
@@ -187,24 +206,18 @@ export const runnerAssignmentPollRoute = defineRoute({
187
206
  const deadline = Date.now() + config.RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS * 1000;
188
207
  const abortController = new AbortController();
189
208
  reply.raw.on('close', ()=>abortController.abort());
190
- while(Date.now() <= deadline){
191
- if (abortController.signal.aborted) return {
192
- activation_token: null
193
- };
194
- const assignment = await getRunnerAssignment(session);
195
- if (assignment) {
196
- const activationToken = await issueRunnerActivationToken({
209
+ const activationToken = await pollForRunnerActivationToken({
210
+ deadline,
211
+ intervalMs: config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS,
212
+ signal: abortController.signal,
213
+ getAssignment: ()=>getRunnerAssignment(session),
214
+ issueActivationToken: ()=>issueRunnerActivationToken({
197
215
  ...session,
198
216
  ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS
199
- });
200
- return {
201
- activation_token: activationToken
202
- };
203
- }
204
- await new Promise((resolve)=>setTimeout(resolve, config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS));
205
- }
217
+ })
218
+ });
206
219
  return {
207
- activation_token: null
220
+ activation_token: activationToken
208
221
  };
209
222
  }
210
223
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/presentation/routes/runner-enrollment.ts"],"sourcesContent":["import {\n requireProvisionerContext,\n requireRunnerControlSessionContext,\n} from '@shipfox/api-auth-context';\nimport {\n attachRunnerControlProviderIdBodySchema,\n createRunnerInstancesBodySchema,\n createRunnerInstancesResponseSchema,\n runnerAssignmentPollResponseSchema,\n runnerBootstrapExchangeBodySchema,\n runnerBootstrapExchangeResponseSchema,\n runnerControlHeartbeatResponseSchema,\n runnerEnrollmentBodySchema,\n} from '@shipfox/api-runners-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {config} from '#config.js';\nimport {getRunnerAssignment, issueRunnerActivationToken} from '#core/runner-activation.js';\nimport {\n attachRunnerControlProviderId,\n createRunnerInstancesWithBootstrapTokens,\n enrollRunnerControlSession,\n exchangeRunnerBootstrapToken,\n RunnerBootstrapTokenInvalidError,\n RunnerControlSessionInvalidError,\n touchRunnerControlSession,\n} from '#core/runner-control-sessions.js';\nimport {attachRunnerInstanceProviderId} from '#core/runner-instances.js';\nimport {runnerBootstrapExchangeCount, runnerControlHeartbeatCount} from '#metrics/instance.js';\nimport {authenticateRunnerControlSession} from '#presentation/auth/index.js';\n\nexport const createRunnerInstancesRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/batch',\n description:\n 'Create provisioner-owned runner instances and one-use bootstrap tokens before launch',\n schema: {\n body: createRunnerInstancesBodySchema,\n response: {200: createRunnerInstancesResponseSchema},\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n const results = await createRunnerInstancesWithBootstrapTokens({\n provisionerId: provisionerTokenId,\n ...(request.body.provider_kind ? {providerKind: request.body.provider_kind} : {}),\n runnerInstances: request.body.runner_instances.map((runner) =>\n runner.template_key ? {templateKey: runner.template_key} : {},\n ),\n ttlSeconds: config.RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS,\n });\n return {\n runner_instances: results.map((result) => ({\n runner_instance_id: result.runnerInstanceId,\n bootstrap_token: result.bootstrapToken,\n })),\n };\n },\n});\n\nexport const attachRunnerInstanceProviderIdRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/:runnerInstanceId/provider-runner',\n description: 'Attach the provider identity after the provisioner launches a runner instance',\n schema: {\n params: z.object({runnerInstanceId: z.string().uuid()}),\n body: attachRunnerControlProviderIdBodySchema,\n response: {200: z.object({attached: z.boolean()})},\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n return {\n attached: await attachRunnerInstanceProviderId({\n runnerInstanceId: request.params.runnerInstanceId,\n provisionerId: provisionerTokenId,\n providerRunnerId: request.body.provider_runner_id,\n }),\n };\n },\n});\n\nexport const exchangeRunnerBootstrapRoute = defineRoute({\n method: 'POST',\n path: '/exchange',\n description: 'Exchange a one-use runner bootstrap token for a workspace-neutral control session',\n schema: {\n body: runnerBootstrapExchangeBodySchema,\n response: {200: runnerBootstrapExchangeResponseSchema},\n },\n errorHandler: (error) => {\n if (error instanceof RunnerBootstrapTokenInvalidError)\n runnerBootstrapExchangeCount.add(1, {outcome: 'rejected'});\n if (error instanceof RunnerBootstrapTokenInvalidError)\n throw new ClientError(error.message, 'runner-bootstrap-token-invalid', {status: 401});\n throw error;\n },\n handler: async (request) => {\n const result = await exchangeRunnerBootstrapToken({\n rawToken: request.body.bootstrap_token,\n ttlSeconds: config.RUNNER_CONTROL_SESSION_TTL_SECONDS,\n });\n runnerBootstrapExchangeCount.add(1, {outcome: 'accepted'});\n return {\n runner_instance_id: result.runnerInstanceId,\n control_session_token: result.controlSessionToken,\n expires_at: result.expiresAt.toISOString(),\n };\n },\n});\n\nexport const enrollRunnerRoute = defineRoute({\n method: 'POST',\n path: '/enrollment',\n description: 'Declare the authenticated runner instance labels and protocol capabilities',\n schema: {body: runnerEnrollmentBodySchema, response: {204: z.null()}},\n preHandler: authenticateRunnerControlSession,\n errorHandler: (error) => {\n if (error instanceof RunnerControlSessionInvalidError)\n throw new ClientError(error.message, 'runner-control-session-invalid', {status: 409});\n throw error;\n },\n handler: async (request, reply) => {\n const session = requireRunnerControlSessionContext(request);\n await enrollRunnerControlSession({\n runnerInstanceId: session.runnerInstanceId,\n provisionerId: session.provisionerId,\n labels: request.body.labels,\n ...(request.body.capabilities ? {capabilities: request.body.capabilities} : {}),\n providerKind: request.body.provider_kind,\n protocolVersion: request.body.protocol_version,\n });\n return await reply.code(204).send();\n },\n});\n\nexport const attachRunnerControlProviderIdRoute = defineRoute({\n method: 'POST',\n path: '/provider-runner',\n description: 'Attach the authenticated runner instance provider identity once',\n schema: {\n body: attachRunnerControlProviderIdBodySchema,\n response: {200: z.object({attached: z.boolean()})},\n },\n preHandler: authenticateRunnerControlSession,\n handler: async (request) => {\n const session = requireRunnerControlSessionContext(request);\n return {\n attached: await attachRunnerControlProviderId({\n ...session,\n providerRunnerId: request.body.provider_runner_id,\n }),\n };\n },\n});\n\nexport const runnerControlHeartbeatRoute = defineRoute({\n method: 'POST',\n path: '/heartbeat',\n description: 'Record liveness for only the authenticated runner instance',\n schema: {response: {200: runnerControlHeartbeatResponseSchema}},\n preHandler: authenticateRunnerControlSession,\n handler: async (request) => {\n const session = requireRunnerControlSessionContext(request);\n await touchRunnerControlSession(session.runnerInstanceId, session.provisionerId);\n runnerControlHeartbeatCount.add(1);\n return {ok: true};\n },\n});\n\nexport const runnerAssignmentPollRoute = defineRoute({\n method: 'GET',\n path: '/assignment',\n description: 'Wait for only the authenticated runner instance assignment',\n schema: {response: {200: runnerAssignmentPollResponseSchema}},\n preHandler: authenticateRunnerControlSession,\n handler: async (request, reply) => {\n const session = requireRunnerControlSessionContext(request);\n const deadline = Date.now() + config.RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS * 1000;\n const abortController = new AbortController();\n reply.raw.on('close', () => abortController.abort());\n while (Date.now() <= deadline) {\n if (abortController.signal.aborted) return {activation_token: null};\n const assignment = await getRunnerAssignment(session);\n if (assignment) {\n const activationToken = await issueRunnerActivationToken({\n ...session,\n ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,\n });\n return {activation_token: activationToken};\n }\n await new Promise((resolve) =>\n setTimeout(resolve, config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS),\n );\n }\n return {activation_token: null};\n },\n});\n"],"names":["requireProvisionerContext","requireRunnerControlSessionContext","attachRunnerControlProviderIdBodySchema","createRunnerInstancesBodySchema","createRunnerInstancesResponseSchema","runnerAssignmentPollResponseSchema","runnerBootstrapExchangeBodySchema","runnerBootstrapExchangeResponseSchema","runnerControlHeartbeatResponseSchema","runnerEnrollmentBodySchema","ClientError","defineRoute","z","config","getRunnerAssignment","issueRunnerActivationToken","attachRunnerControlProviderId","createRunnerInstancesWithBootstrapTokens","enrollRunnerControlSession","exchangeRunnerBootstrapToken","RunnerBootstrapTokenInvalidError","RunnerControlSessionInvalidError","touchRunnerControlSession","attachRunnerInstanceProviderId","runnerBootstrapExchangeCount","runnerControlHeartbeatCount","authenticateRunnerControlSession","createRunnerInstancesRoute","method","path","description","schema","body","response","handler","request","provisionerTokenId","results","provisionerId","provider_kind","providerKind","runnerInstances","runner_instances","map","runner","template_key","templateKey","ttlSeconds","RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS","result","runner_instance_id","runnerInstanceId","bootstrap_token","bootstrapToken","attachRunnerInstanceProviderIdRoute","params","object","string","uuid","attached","boolean","providerRunnerId","provider_runner_id","exchangeRunnerBootstrapRoute","errorHandler","error","add","outcome","message","status","rawToken","RUNNER_CONTROL_SESSION_TTL_SECONDS","control_session_token","controlSessionToken","expires_at","expiresAt","toISOString","enrollRunnerRoute","null","preHandler","reply","session","labels","capabilities","protocolVersion","protocol_version","code","send","attachRunnerControlProviderIdRoute","runnerControlHeartbeatRoute","ok","runnerAssignmentPollRoute","deadline","Date","now","RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS","abortController","AbortController","raw","on","abort","signal","aborted","activation_token","assignment","activationToken","RUNNER_ACTIVATION_TOKEN_TTL_SECONDS","Promise","resolve","setTimeout","RUNNER_ASSIGNMENT_POLL_INTERVAL_MS"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/presentation/routes/runner-enrollment.ts"],"sourcesContent":["import {\n requireProvisionerContext,\n requireRunnerControlSessionContext,\n} from '@shipfox/api-auth-context';\nimport {\n attachRunnerControlProviderIdBodySchema,\n createRunnerInstancesBodySchema,\n createRunnerInstancesResponseSchema,\n runnerAssignmentPollResponseSchema,\n runnerBootstrapExchangeBodySchema,\n runnerBootstrapExchangeResponseSchema,\n runnerControlHeartbeatResponseSchema,\n runnerEnrollmentBodySchema,\n runnerEnrollmentResponseSchema,\n} from '@shipfox/api-runners-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {z} from 'zod';\nimport {config} from '#config.js';\nimport {getRunnerAssignment, issueRunnerActivationToken} from '#core/runner-activation.js';\nimport {\n attachRunnerControlProviderId,\n createRunnerInstancesWithBootstrapTokens,\n enrollRunnerControlSession,\n exchangeRunnerBootstrapToken,\n RunnerBootstrapTokenInvalidError,\n RunnerControlSessionInvalidError,\n touchRunnerControlSession,\n} from '#core/runner-control-sessions.js';\nimport {attachRunnerInstanceProviderId} from '#core/runner-instances.js';\nimport {runnerBootstrapExchangeCount, runnerControlHeartbeatCount} from '#metrics/instance.js';\nimport {authenticateRunnerControlSession} from '#presentation/auth/index.js';\n\nexport const createRunnerInstancesRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/batch',\n description:\n 'Create provisioner-owned runner instances and one-use bootstrap tokens before launch',\n schema: {\n body: createRunnerInstancesBodySchema,\n response: {200: createRunnerInstancesResponseSchema},\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n const results = await createRunnerInstancesWithBootstrapTokens({\n provisionerId: provisionerTokenId,\n ...(request.body.provider_kind ? {providerKind: request.body.provider_kind} : {}),\n runnerInstances: request.body.runner_instances.map((runner) => ({\n ...(runner.template_key ? {templateKey: runner.template_key} : {}),\n ...(runner.reservation_id ? {reservationId: runner.reservation_id} : {}),\n })),\n ttlSeconds: config.RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS,\n });\n return {\n runner_instances: results.map((result) => ({\n runner_instance_id: result.runnerInstanceId,\n bootstrap_token: result.bootstrapToken,\n })),\n };\n },\n});\n\nexport const attachRunnerInstanceProviderIdRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/:runnerInstanceId/provider-runner',\n description: 'Attach the provider identity after the provisioner launches a runner instance',\n schema: {\n params: z.object({runnerInstanceId: z.string().uuid()}),\n body: attachRunnerControlProviderIdBodySchema,\n response: {200: z.object({attached: z.boolean()})},\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n return {\n attached: await attachRunnerInstanceProviderId({\n runnerInstanceId: request.params.runnerInstanceId,\n provisionerId: provisionerTokenId,\n providerRunnerId: request.body.provider_runner_id,\n }),\n };\n },\n});\n\nexport const exchangeRunnerBootstrapRoute = defineRoute({\n method: 'POST',\n path: '/exchange',\n description: 'Exchange a one-use runner bootstrap token for a workspace-neutral control session',\n schema: {\n body: runnerBootstrapExchangeBodySchema,\n response: {200: runnerBootstrapExchangeResponseSchema},\n },\n errorHandler: (error) => {\n if (error instanceof RunnerBootstrapTokenInvalidError)\n runnerBootstrapExchangeCount.add(1, {outcome: 'rejected'});\n if (error instanceof RunnerBootstrapTokenInvalidError)\n throw new ClientError(error.message, 'runner-bootstrap-token-invalid', {status: 401});\n throw error;\n },\n handler: async (request) => {\n const result = await exchangeRunnerBootstrapToken({\n rawToken: request.body.bootstrap_token,\n ttlSeconds: config.RUNNER_CONTROL_SESSION_TTL_SECONDS,\n });\n runnerBootstrapExchangeCount.add(1, {outcome: 'accepted'});\n return {\n runner_instance_id: result.runnerInstanceId,\n control_session_token: result.controlSessionToken,\n expires_at: result.expiresAt.toISOString(),\n };\n },\n});\n\nexport const enrollRunnerRoute = defineRoute({\n method: 'POST',\n path: '/enrollment',\n description: 'Declare the authenticated runner instance labels and protocol capabilities',\n schema: {body: runnerEnrollmentBodySchema, response: {200: runnerEnrollmentResponseSchema}},\n preHandler: authenticateRunnerControlSession,\n errorHandler: (error) => {\n if (error instanceof RunnerControlSessionInvalidError)\n throw new ClientError(error.message, 'runner-control-session-invalid', {status: 409});\n throw error;\n },\n handler: async (request) => {\n const session = requireRunnerControlSessionContext(request);\n const activationToken = await enrollRunnerControlSession({\n runnerInstanceId: session.runnerInstanceId,\n provisionerId: session.provisionerId,\n labels: request.body.labels,\n ...(request.body.capabilities ? {capabilities: request.body.capabilities} : {}),\n providerKind: request.body.provider_kind,\n protocolVersion: request.body.protocol_version,\n });\n return {activation_token: activationToken};\n },\n});\n\nexport const attachRunnerControlProviderIdRoute = defineRoute({\n method: 'POST',\n path: '/provider-runner',\n description: 'Attach the authenticated runner instance provider identity once',\n schema: {\n body: attachRunnerControlProviderIdBodySchema,\n response: {200: z.object({attached: z.boolean()})},\n },\n preHandler: authenticateRunnerControlSession,\n handler: async (request) => {\n const session = requireRunnerControlSessionContext(request);\n return {\n attached: await attachRunnerControlProviderId({\n ...session,\n providerRunnerId: request.body.provider_runner_id,\n }),\n };\n },\n});\n\nexport const runnerControlHeartbeatRoute = defineRoute({\n method: 'POST',\n path: '/heartbeat',\n description: 'Record liveness for only the authenticated runner instance',\n schema: {response: {200: runnerControlHeartbeatResponseSchema}},\n preHandler: authenticateRunnerControlSession,\n handler: async (request) => {\n const session = requireRunnerControlSessionContext(request);\n await touchRunnerControlSession(session.runnerInstanceId, session.provisionerId);\n runnerControlHeartbeatCount.add(1);\n return {ok: true};\n },\n});\n\ntype RunnerAssignmentPollParams = {\n deadline: number;\n intervalMs: number;\n signal: AbortSignal;\n getAssignment: () => Promise<unknown | null>;\n issueActivationToken: () => Promise<string | null>;\n};\nexport async function pollForRunnerActivationToken(\n params: RunnerAssignmentPollParams,\n): Promise<string | null> {\n while (Date.now() <= params.deadline) {\n if (params.signal.aborted) return null;\n const assignment = await params.getAssignment();\n if (assignment) {\n const activationToken = await params.issueActivationToken();\n if (activationToken) return activationToken;\n }\n await new Promise((resolve) => setTimeout(resolve, params.intervalMs));\n }\n return null;\n}\nexport const runnerAssignmentPollRoute = defineRoute({\n method: 'GET',\n path: '/assignment',\n description: 'Wait for only the authenticated runner instance assignment',\n schema: {response: {200: runnerAssignmentPollResponseSchema}},\n preHandler: authenticateRunnerControlSession,\n handler: async (request, reply) => {\n const session = requireRunnerControlSessionContext(request);\n const deadline = Date.now() + config.RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS * 1000;\n const abortController = new AbortController();\n reply.raw.on('close', () => abortController.abort());\n const activationToken = await pollForRunnerActivationToken({\n deadline,\n intervalMs: config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS,\n signal: abortController.signal,\n getAssignment: () => getRunnerAssignment(session),\n issueActivationToken: () =>\n issueRunnerActivationToken({\n ...session,\n ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,\n }),\n });\n return {activation_token: activationToken};\n },\n});\n"],"names":["requireProvisionerContext","requireRunnerControlSessionContext","attachRunnerControlProviderIdBodySchema","createRunnerInstancesBodySchema","createRunnerInstancesResponseSchema","runnerAssignmentPollResponseSchema","runnerBootstrapExchangeBodySchema","runnerBootstrapExchangeResponseSchema","runnerControlHeartbeatResponseSchema","runnerEnrollmentBodySchema","runnerEnrollmentResponseSchema","ClientError","defineRoute","z","config","getRunnerAssignment","issueRunnerActivationToken","attachRunnerControlProviderId","createRunnerInstancesWithBootstrapTokens","enrollRunnerControlSession","exchangeRunnerBootstrapToken","RunnerBootstrapTokenInvalidError","RunnerControlSessionInvalidError","touchRunnerControlSession","attachRunnerInstanceProviderId","runnerBootstrapExchangeCount","runnerControlHeartbeatCount","authenticateRunnerControlSession","createRunnerInstancesRoute","method","path","description","schema","body","response","handler","request","provisionerTokenId","results","provisionerId","provider_kind","providerKind","runnerInstances","runner_instances","map","runner","template_key","templateKey","reservation_id","reservationId","ttlSeconds","RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS","result","runner_instance_id","runnerInstanceId","bootstrap_token","bootstrapToken","attachRunnerInstanceProviderIdRoute","params","object","string","uuid","attached","boolean","providerRunnerId","provider_runner_id","exchangeRunnerBootstrapRoute","errorHandler","error","add","outcome","message","status","rawToken","RUNNER_CONTROL_SESSION_TTL_SECONDS","control_session_token","controlSessionToken","expires_at","expiresAt","toISOString","enrollRunnerRoute","preHandler","session","activationToken","labels","capabilities","protocolVersion","protocol_version","activation_token","attachRunnerControlProviderIdRoute","runnerControlHeartbeatRoute","ok","pollForRunnerActivationToken","Date","now","deadline","signal","aborted","assignment","getAssignment","issueActivationToken","Promise","resolve","setTimeout","intervalMs","runnerAssignmentPollRoute","reply","RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS","abortController","AbortController","raw","on","abort","RUNNER_ASSIGNMENT_POLL_INTERVAL_MS","RUNNER_ACTIVATION_TOKEN_TTL_SECONDS"],"mappings":"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"}