@shipfox/api-runners-dto 5.0.0 → 7.0.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.
Files changed (73) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +34 -0
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/inter-module.d.ts +64 -0
  8. package/dist/inter-module.d.ts.map +1 -0
  9. package/dist/inter-module.js +57 -0
  10. package/dist/inter-module.js.map +1 -0
  11. package/dist/schemas/assign-runner-instances.d.ts +11 -0
  12. package/dist/schemas/assign-runner-instances.d.ts.map +1 -0
  13. package/dist/schemas/assign-runner-instances.js +15 -0
  14. package/dist/schemas/assign-runner-instances.js.map +1 -0
  15. package/dist/schemas/index.d.ts +4 -3
  16. package/dist/schemas/index.d.ts.map +1 -1
  17. package/dist/schemas/index.js +4 -3
  18. package/dist/schemas/index.js.map +1 -1
  19. package/dist/schemas/poll-demand.d.ts +5 -1
  20. package/dist/schemas/poll-demand.d.ts.map +1 -1
  21. package/dist/schemas/poll-demand.js +4 -2
  22. package/dist/schemas/poll-demand.js.map +1 -1
  23. package/dist/schemas/provisioner-token.d.ts +10 -2
  24. package/dist/schemas/provisioner-token.d.ts.map +1 -1
  25. package/dist/schemas/provisioner-token.js +15 -6
  26. package/dist/schemas/provisioner-token.js.map +1 -1
  27. package/dist/schemas/{reconcile-provisioned-runners.d.ts → reconcile-runner-instances.d.ts} +12 -12
  28. package/dist/schemas/reconcile-runner-instances.d.ts.map +1 -0
  29. package/dist/schemas/reconcile-runner-instances.js +36 -0
  30. package/dist/schemas/reconcile-runner-instances.js.map +1 -0
  31. package/dist/schemas/register.d.ts +1 -0
  32. package/dist/schemas/register.d.ts.map +1 -1
  33. package/dist/schemas/register.js +2 -1
  34. package/dist/schemas/register.js.map +1 -1
  35. package/dist/schemas/{report-provisioned-runners.d.ts → report-runner-instances.d.ts} +17 -15
  36. package/dist/schemas/report-runner-instances.d.ts.map +1 -0
  37. package/dist/schemas/{report-provisioned-runners.js → report-runner-instances.js} +13 -12
  38. package/dist/schemas/report-runner-instances.js.map +1 -0
  39. package/dist/schemas/runner-enrollment.d.ts +51 -0
  40. package/dist/schemas/runner-enrollment.d.ts.map +1 -0
  41. package/dist/schemas/runner-enrollment.js +40 -0
  42. package/dist/schemas/runner-enrollment.js.map +1 -0
  43. package/dist/tsconfig.test.tsbuildinfo +1 -1
  44. package/package.json +6 -1
  45. package/src/index.ts +34 -26
  46. package/src/inter-module.test.ts +40 -0
  47. package/src/inter-module.ts +51 -0
  48. package/src/schemas/assign-runner-instances.test.ts +27 -0
  49. package/src/schemas/assign-runner-instances.ts +19 -0
  50. package/src/schemas/index.ts +40 -30
  51. package/src/schemas/poll-demand.test.ts +1 -1
  52. package/src/schemas/poll-demand.ts +4 -2
  53. package/src/schemas/provisioner-token.test.ts +9 -0
  54. package/src/schemas/provisioner-token.ts +6 -4
  55. package/src/schemas/{reconcile-provisioned-runners.test.ts → reconcile-runner-instances.test.ts} +21 -21
  56. package/src/schemas/reconcile-runner-instances.ts +58 -0
  57. package/src/schemas/register.ts +1 -1
  58. package/src/schemas/{report-provisioned-runners.test.ts → report-runner-instances.test.ts} +16 -16
  59. package/src/schemas/{report-provisioned-runners.ts → report-runner-instances.ts} +16 -20
  60. package/src/schemas/runner-enrollment.ts +49 -0
  61. package/tsconfig.build.tsbuildinfo +1 -1
  62. package/dist/schemas/mint-registration-tokens.d.ts +0 -28
  63. package/dist/schemas/mint-registration-tokens.d.ts.map +0 -1
  64. package/dist/schemas/mint-registration-tokens.js +0 -24
  65. package/dist/schemas/mint-registration-tokens.js.map +0 -1
  66. package/dist/schemas/reconcile-provisioned-runners.d.ts.map +0 -1
  67. package/dist/schemas/reconcile-provisioned-runners.js +0 -36
  68. package/dist/schemas/reconcile-provisioned-runners.js.map +0 -1
  69. package/dist/schemas/report-provisioned-runners.d.ts.map +0 -1
  70. package/dist/schemas/report-provisioned-runners.js.map +0 -1
  71. package/src/schemas/mint-registration-tokens.test.ts +0 -28
  72. package/src/schemas/mint-registration-tokens.ts +0 -46
  73. package/src/schemas/reconcile-provisioned-runners.ts +0 -61
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-runners-dto",
3
3
  "license": "MIT",
4
- "version": "5.0.0",
4
+ "version": "7.0.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -19,10 +19,15 @@
19
19
  ".": {
20
20
  "types": "./dist/index.d.ts",
21
21
  "default": "./dist/index.js"
22
+ },
23
+ "./inter-module": {
24
+ "types": "./dist/inter-module.d.ts",
25
+ "default": "./dist/inter-module.js"
22
26
  }
23
27
  },
24
28
  "dependencies": {
25
29
  "zod": "^4.4.3",
30
+ "@shipfox/inter-module": "0.2.0",
26
31
  "@shipfox/runner-labels": "0.1.1"
27
32
  },
28
33
  "devDependencies": {
package/src/index.ts CHANGED
@@ -3,20 +3,29 @@ export {
3
3
  type ActiveRunnerDto,
4
4
  type ActiveRunnerStateDto,
5
5
  type ActiveRunnersResponseDto,
6
+ type AssignRunnerInstancesBodyDto,
7
+ type AssignRunnerInstancesResponseDto,
6
8
  activeProvisionerDtoSchema,
7
9
  activeRunnerDtoSchema,
8
10
  activeRunnerStateSchema,
9
11
  activeRunnersResponseSchema,
12
+ assignRunnerInstancesBodySchema,
13
+ assignRunnerInstancesResponseSchema,
14
+ attachRunnerControlProviderIdBodySchema,
10
15
  type ClaimedJobResponseDto,
11
16
  type CreateManualRegistrationTokenBodyDto,
12
17
  type CreateManualRegistrationTokenResponseDto,
13
18
  type CreateProvisionerTokenBodyDto,
14
19
  type CreateProvisionerTokenResponseDto,
20
+ type CreateRunnerInstancesBodyDto,
21
+ type CreateRunnerInstancesResponseDto,
15
22
  claimedJobResponseSchema,
16
23
  createManualRegistrationTokenBodySchema,
17
24
  createManualRegistrationTokenResponseSchema,
18
25
  createProvisionerTokenBodySchema,
19
26
  createProvisionerTokenResponseSchema,
27
+ createRunnerInstancesBodySchema,
28
+ createRunnerInstancesResponseSchema,
20
29
  type DemandStatDto,
21
30
  demandStatSchema,
22
31
  type HeartbeatBodyDto,
@@ -30,65 +39,64 @@ export {
30
39
  listManualRegistrationTokensResponseSchema,
31
40
  listProvisionerTokensResponseSchema,
32
41
  MAX_MANUAL_REGISTRATION_TOKEN_TTL_SECONDS,
33
- MAX_OBSERVED_PROVISIONED_RUNNER_ID_LENGTH,
42
+ MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH,
34
43
  MAX_PROVIDER_KIND_LENGTH,
35
- MAX_PROVISIONED_RUNNER_REASON_LENGTH,
36
- MAX_PROVISIONED_RUNNER_REPORT_EVENTS,
44
+ MAX_PROVIDER_RUNNER_REASON_LENGTH,
45
+ MAX_PROVIDER_RUNNER_REPORT_EVENTS,
37
46
  MAX_PROVISIONER_TOKEN_TTL_SECONDS,
38
47
  MAX_RECONCILE_OBSERVED_RUNNERS,
39
48
  type ManualRegistrationTokenDto,
40
- type MintedRegistrationTokenDto,
41
- type MintRegistrationTokensBatchBodyDto,
42
- type MintRegistrationTokensBatchResponseDto,
43
- type MintRegistrationTokensProvisionedRunnerDto,
44
49
  manualRegistrationTokenDtoSchema,
45
- mintedRegistrationTokenSchema,
46
- mintRegistrationTokensBatchBodySchema,
47
- mintRegistrationTokensBatchResponseSchema,
48
- mintRegistrationTokensProvisionedRunnerSchema,
49
50
  type PollDemandBodyDto,
50
51
  type PollDemandResponseDto,
51
52
  type PollDemandTemplateDto,
52
- type ProvisionedRunnerReportEventDto,
53
- type ProvisionedRunnerStateDto,
54
53
  type ProvisionerIdentityResponseDto,
55
54
  type ProvisionerTokenDto,
56
55
  pollDemandBodySchema,
57
56
  pollDemandResponseSchema,
58
57
  pollDemandTemplateSchema,
59
58
  providerKindSchema,
60
- provisionedRunnerReportEventSchema,
61
- provisionedRunnerStateSchema,
59
+ providerRunnerReportEventSchema,
60
+ providerRunnerStateSchema,
62
61
  provisionerIdentityResponseSchema,
63
62
  provisionerTokenDtoSchema,
64
- REGISTRATION_TOKEN_BATCH_HARD_MAX,
65
63
  type ReconcileDesiredIntentDto,
66
64
  type ReconciledBoundJobDto,
67
- type ReconciledProvisionedRunnerDto,
68
- type ReconcileProvisionedRunnersBodyDto,
69
- type ReconcileProvisionedRunnersResponseDto,
65
+ type ReconciledRunnerInstanceDto,
66
+ type ReconcileRunnerInstancesBodyDto,
67
+ type ReconcileRunnerInstancesResponseDto,
70
68
  type RegisterRunnerBodyDto,
71
69
  type RegisterRunnerResponseDto,
72
- type ReportProvisionedRunnersBodyDto,
73
- type ReportProvisionedRunnersResponseDto,
70
+ type ReportRunnerInstancesBodyDto,
71
+ type ReportRunnerInstancesResponseDto,
74
72
  type ReservationGrantDto,
75
73
  type RevokeManualRegistrationTokenResponseDto,
76
74
  type RevokeProvisionerTokenResponseDto,
77
75
  RUNNER_SESSION_EXHAUSTED_CODE,
76
+ type RunnerBootstrapExchangeBodyDto,
77
+ type RunnerBootstrapExchangeResponseDto,
78
+ type RunnerEnrollmentBodyDto,
78
79
  type RunnerHarnessToolCapabilitiesDto,
80
+ type RunnerInstanceReportEventDto,
81
+ type RunnerInstanceStateDto,
79
82
  type RunnerToolCapabilitiesDto,
80
83
  reconcileDesiredIntentSchema,
81
84
  reconciledBoundJobSchema,
82
- reconciledProvisionedRunnerSchema,
83
- reconcileProvisionedRunnersBodySchema,
84
- reconcileProvisionedRunnersResponseSchema,
85
+ reconciledRunnerInstanceSchema,
86
+ reconcileRunnerInstancesBodySchema,
87
+ reconcileRunnerInstancesResponseSchema,
85
88
  registerRunnerBodySchema,
86
89
  registerRunnerResponseSchema,
87
- reportProvisionedRunnersBodySchema,
88
- reportProvisionedRunnersResponseSchema,
90
+ reportRunnerInstancesBodySchema,
91
+ reportRunnerInstancesResponseSchema,
89
92
  reservationGrantSchema,
90
93
  revokeManualRegistrationTokenResponseSchema,
91
94
  revokeProvisionerTokenResponseSchema,
95
+ runnerAssignmentPollResponseSchema,
96
+ runnerBootstrapExchangeBodySchema,
97
+ runnerBootstrapExchangeResponseSchema,
98
+ runnerControlHeartbeatResponseSchema,
99
+ runnerEnrollmentBodySchema,
92
100
  runnerHarnessToolCapabilitiesSchema,
93
101
  runnerToolCapabilitiesSchema,
94
102
  } from '#schemas/index.js';
@@ -0,0 +1,40 @@
1
+ import {runnersInterModuleContract} from './inter-module.js';
2
+
3
+ const id = '00000000-0000-4000-8000-000000000001';
4
+
5
+ describe('runnersInterModuleContract', () => {
6
+ test('accepts stable job-execution identities for idempotent commands', () => {
7
+ const input = runnersInterModuleContract.methods.enqueueJobExecution.input.parse({
8
+ workspaceId: id,
9
+ workflowRunId: id,
10
+ workflowRunAttemptId: id,
11
+ jobId: id,
12
+ jobExecutionId: id,
13
+ projectId: id,
14
+ requiredLabels: ['linux'],
15
+ });
16
+
17
+ expect(input.jobExecutionId).toBe(id);
18
+ });
19
+
20
+ test('exposes bounded JSON capability results', () => {
21
+ const result =
22
+ runnersInterModuleContract.methods.getEffectiveRunnerToolCapabilities.output.parse({
23
+ capabilities: {harnesses: {pi: {tools: ['read']}}},
24
+ reportFresh: true,
25
+ });
26
+
27
+ expect(result).toEqual({
28
+ capabilities: {harnesses: {pi: {tools: ['read']}}},
29
+ reportFresh: true,
30
+ });
31
+ });
32
+
33
+ test('defines the scheduling validation failure', () => {
34
+ const details = runnersInterModuleContract.methods.enqueueJobExecution.errors[
35
+ 'empty-required-labels'
36
+ ].parse({});
37
+
38
+ expect(details).toEqual({});
39
+ });
40
+ });
@@ -0,0 +1,51 @@
1
+ import {defineInterModuleContract, type InterModuleClient} from '@shipfox/inter-module';
2
+ import {z} from 'zod';
3
+ import {runnerToolCapabilitiesSchema} from '#schemas/tool-capabilities.js';
4
+
5
+ const idSchema = z.string().uuid();
6
+
7
+ export const runnersInterModuleContract = defineInterModuleContract({
8
+ module: 'runners',
9
+ methods: {
10
+ enqueueJobExecution: {
11
+ input: z.object({
12
+ workspaceId: idSchema,
13
+ workflowRunId: idSchema,
14
+ workflowRunAttemptId: idSchema,
15
+ jobId: idSchema,
16
+ jobExecutionId: idSchema,
17
+ projectId: idSchema,
18
+ requiredLabels: z.array(z.string()),
19
+ }),
20
+ output: z.object({}),
21
+ errors: {
22
+ 'empty-required-labels': z.object({}),
23
+ },
24
+ },
25
+ releaseJobExecution: {
26
+ input: z.object({jobExecutionId: idSchema}),
27
+ output: z.object({}),
28
+ },
29
+ cancelJobs: {
30
+ input: z.object({jobIds: z.array(idSchema)}),
31
+ output: z.object({}),
32
+ },
33
+ getLeaseState: {
34
+ input: z.object({
35
+ jobId: idSchema,
36
+ jobExecutionId: idSchema,
37
+ runnerSessionId: idSchema,
38
+ }),
39
+ output: z.object({active: z.boolean()}),
40
+ },
41
+ getEffectiveRunnerToolCapabilities: {
42
+ input: z.object({runnerSessionId: idSchema}),
43
+ output: z.object({
44
+ capabilities: runnerToolCapabilitiesSchema,
45
+ reportFresh: z.boolean(),
46
+ }),
47
+ },
48
+ },
49
+ });
50
+
51
+ export type RunnersInterModuleClient = InterModuleClient<typeof runnersInterModuleContract>;
@@ -0,0 +1,27 @@
1
+ import {assignRunnerInstancesBodySchema} from './assign-runner-instances.js';
2
+
3
+ describe('assignRunnerInstancesBodySchema', () => {
4
+ it('accepts a reservation and unique runner instances', () => {
5
+ const result = assignRunnerInstancesBodySchema.safeParse({
6
+ reservation_id: '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0001',
7
+ runner_instance_ids: [
8
+ '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0002',
9
+ '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0003',
10
+ ],
11
+ });
12
+
13
+ expect(result.success).toBe(true);
14
+ });
15
+
16
+ it('rejects duplicate runner instances', () => {
17
+ const result = assignRunnerInstancesBodySchema.safeParse({
18
+ reservation_id: '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0001',
19
+ runner_instance_ids: [
20
+ '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0002',
21
+ '018f0d4c-5f42-7b7e-9d9b-4a7d8e6f0002',
22
+ ],
23
+ });
24
+
25
+ expect(result.success).toBe(false);
26
+ });
27
+ });
@@ -0,0 +1,19 @@
1
+ import {z} from 'zod';
2
+
3
+ export const assignRunnerInstancesBodySchema = z
4
+ .object({
5
+ reservation_id: z.string().uuid(),
6
+ runner_instance_ids: z.array(z.string().uuid()).min(1).max(1000),
7
+ })
8
+ .strict()
9
+ .refine((body) => new Set(body.runner_instance_ids).size === body.runner_instance_ids.length, {
10
+ message: 'runner_instance_ids values must be unique',
11
+ path: ['runner_instance_ids'],
12
+ });
13
+
14
+ export const assignRunnerInstancesResponseSchema = z.object({
15
+ runner_instance_ids: z.array(z.string().uuid()),
16
+ });
17
+
18
+ export type AssignRunnerInstancesBodyDto = z.infer<typeof assignRunnerInstancesBodySchema>;
19
+ export type AssignRunnerInstancesResponseDto = z.infer<typeof assignRunnerInstancesResponseSchema>;
@@ -1,3 +1,9 @@
1
+ export {
2
+ type AssignRunnerInstancesBodyDto,
3
+ type AssignRunnerInstancesResponseDto,
4
+ assignRunnerInstancesBodySchema,
5
+ assignRunnerInstancesResponseSchema,
6
+ } from './assign-runner-instances.js';
1
7
  export {
2
8
  type ClaimedJobResponseDto,
3
9
  claimedJobResponseSchema,
@@ -28,17 +34,6 @@ export {
28
34
  type RevokeManualRegistrationTokenResponseDto,
29
35
  revokeManualRegistrationTokenResponseSchema,
30
36
  } from './manual-registration-token.js';
31
- export {
32
- type MintedRegistrationTokenDto,
33
- type MintRegistrationTokensBatchBodyDto,
34
- type MintRegistrationTokensBatchResponseDto,
35
- type MintRegistrationTokensProvisionedRunnerDto,
36
- mintedRegistrationTokenSchema,
37
- mintRegistrationTokensBatchBodySchema,
38
- mintRegistrationTokensBatchResponseSchema,
39
- mintRegistrationTokensProvisionedRunnerSchema,
40
- REGISTRATION_TOKEN_BATCH_HARD_MAX,
41
- } from './mint-registration-tokens.js';
42
37
  export {
43
38
  type DemandStatDto,
44
39
  demandStatSchema,
@@ -67,19 +62,19 @@ export {
67
62
  revokeProvisionerTokenResponseSchema,
68
63
  } from './provisioner-token.js';
69
64
  export {
70
- MAX_OBSERVED_PROVISIONED_RUNNER_ID_LENGTH,
65
+ MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH,
71
66
  MAX_RECONCILE_OBSERVED_RUNNERS,
72
67
  type ReconcileDesiredIntentDto,
73
68
  type ReconciledBoundJobDto,
74
- type ReconciledProvisionedRunnerDto,
75
- type ReconcileProvisionedRunnersBodyDto,
76
- type ReconcileProvisionedRunnersResponseDto,
69
+ type ReconciledRunnerInstanceDto,
70
+ type ReconcileRunnerInstancesBodyDto,
71
+ type ReconcileRunnerInstancesResponseDto,
77
72
  reconcileDesiredIntentSchema,
78
73
  reconciledBoundJobSchema,
79
- reconciledProvisionedRunnerSchema,
80
- reconcileProvisionedRunnersBodySchema,
81
- reconcileProvisionedRunnersResponseSchema,
82
- } from './reconcile-provisioned-runners.js';
74
+ reconciledRunnerInstanceSchema,
75
+ reconcileRunnerInstancesBodySchema,
76
+ reconcileRunnerInstancesResponseSchema,
77
+ } from './reconcile-runner-instances.js';
83
78
  export {
84
79
  type RegisterRunnerBodyDto,
85
80
  type RegisterRunnerResponseDto,
@@ -95,18 +90,33 @@ export {
95
90
  activeRunnerStateSchema,
96
91
  activeRunnersResponseSchema,
97
92
  MAX_PROVIDER_KIND_LENGTH,
98
- MAX_PROVISIONED_RUNNER_REASON_LENGTH,
99
- MAX_PROVISIONED_RUNNER_REPORT_EVENTS,
100
- type ProvisionedRunnerReportEventDto,
101
- type ProvisionedRunnerStateDto,
93
+ MAX_PROVIDER_RUNNER_REASON_LENGTH,
94
+ MAX_PROVIDER_RUNNER_REPORT_EVENTS,
102
95
  providerKindSchema,
103
- provisionedRunnerReportEventSchema,
104
- provisionedRunnerStateSchema,
105
- type ReportProvisionedRunnersBodyDto,
106
- type ReportProvisionedRunnersResponseDto,
107
- reportProvisionedRunnersBodySchema,
108
- reportProvisionedRunnersResponseSchema,
109
- } from './report-provisioned-runners.js';
96
+ providerRunnerReportEventSchema,
97
+ providerRunnerStateSchema,
98
+ type ReportRunnerInstancesBodyDto,
99
+ type ReportRunnerInstancesResponseDto,
100
+ type RunnerInstanceReportEventDto,
101
+ type RunnerInstanceStateDto,
102
+ reportRunnerInstancesBodySchema,
103
+ reportRunnerInstancesResponseSchema,
104
+ } from './report-runner-instances.js';
105
+ export {
106
+ attachRunnerControlProviderIdBodySchema,
107
+ type CreateRunnerInstancesBodyDto,
108
+ type CreateRunnerInstancesResponseDto,
109
+ createRunnerInstancesBodySchema,
110
+ createRunnerInstancesResponseSchema,
111
+ type RunnerBootstrapExchangeBodyDto,
112
+ type RunnerBootstrapExchangeResponseDto,
113
+ type RunnerEnrollmentBodyDto,
114
+ runnerAssignmentPollResponseSchema,
115
+ runnerBootstrapExchangeBodySchema,
116
+ runnerBootstrapExchangeResponseSchema,
117
+ runnerControlHeartbeatResponseSchema,
118
+ runnerEnrollmentBodySchema,
119
+ } from './runner-enrollment.js';
110
120
  export {
111
121
  type RunnerHarnessToolCapabilitiesDto,
112
122
  type RunnerToolCapabilitiesDto,
@@ -19,7 +19,7 @@ describe('pollDemandResponseSchema', () => {
19
19
  expires_at: 'not-a-date',
20
20
  },
21
21
  ],
22
- terminate_provisioned_runner_ids: [],
22
+ terminate_provider_runner_ids: [],
23
23
  });
24
24
 
25
25
  expect(result.success).toBe(false);
@@ -13,10 +13,11 @@ export const pollDemandTemplateSchema = z.object({
13
13
  export const pollDemandBodySchema = z.object({
14
14
  wait_seconds: z.number().int().min(0).optional(),
15
15
  max_reservations: z.number().int().min(0).max(1000),
16
- templates: z.array(pollDemandTemplateSchema).min(1).max(100),
16
+ templates: z.array(pollDemandTemplateSchema).max(100),
17
17
  });
18
18
 
19
19
  export const demandStatSchema = z.object({
20
+ workspace_id: z.string().uuid().optional(),
20
21
  labels: z.array(z.string()),
21
22
  queued: z.number().int().min(0),
22
23
  reserved: z
@@ -31,6 +32,7 @@ export const demandStatSchema = z.object({
31
32
 
32
33
  export const reservationGrantSchema = z.object({
33
34
  reservation_id: z.string().uuid(),
35
+ workspace_id: z.string().uuid().optional(),
34
36
  labels: z.array(z.string()),
35
37
  count: z.number().int().positive(),
36
38
  expires_at: z.string().datetime(),
@@ -39,7 +41,7 @@ export const reservationGrantSchema = z.object({
39
41
  export const pollDemandResponseSchema = z.object({
40
42
  stats: z.array(demandStatSchema),
41
43
  reservations: z.array(reservationGrantSchema),
42
- terminate_provisioned_runner_ids: z.array(z.string()),
44
+ terminate_provider_runner_ids: z.array(z.string()),
43
45
  });
44
46
 
45
47
  export type PollDemandTemplateDto = z.infer<typeof pollDemandTemplateSchema>;
@@ -28,6 +28,7 @@ describe('provisioner token schemas', () => {
28
28
  it('parses provisioner identity responses', () => {
29
29
  const identity = {
30
30
  id: crypto.randomUUID(),
31
+ scope: 'workspace',
31
32
  workspace_id: crypto.randomUUID(),
32
33
  };
33
34
 
@@ -35,4 +36,12 @@ describe('provisioner token schemas', () => {
35
36
 
36
37
  expect(result).toEqual(identity);
37
38
  });
39
+
40
+ it('parses installation provisioner identities without a workspace', () => {
41
+ const identity = {id: crypto.randomUUID(), scope: 'installation'};
42
+
43
+ const result = provisionerIdentityResponseSchema.parse(identity);
44
+
45
+ expect(result).toEqual(identity);
46
+ });
38
47
  });
@@ -22,6 +22,7 @@ export const createProvisionerTokenResponseSchema = z.object({
22
22
  last_seen_at: z.string().nullable(),
23
23
  created_at: z.string(),
24
24
  updated_at: z.string(),
25
+ scope: z.literal('workspace'),
25
26
  });
26
27
 
27
28
  export type CreateProvisionerTokenResponseDto = z.infer<
@@ -40,6 +41,7 @@ export const provisionerTokenDtoSchema = z.object({
40
41
  last_seen_at: z.string().nullable(),
41
42
  created_at: z.string(),
42
43
  updated_at: z.string(),
44
+ scope: z.literal('workspace'),
43
45
  });
44
46
 
45
47
  export type ProvisionerTokenDto = z.infer<typeof provisionerTokenDtoSchema>;
@@ -56,9 +58,9 @@ export type RevokeProvisionerTokenResponseDto = z.infer<
56
58
  typeof revokeProvisionerTokenResponseSchema
57
59
  >;
58
60
 
59
- export const provisionerIdentityResponseSchema = z.object({
60
- id: z.string().uuid(),
61
- workspace_id: z.string().uuid(),
62
- });
61
+ export const provisionerIdentityResponseSchema = z.discriminatedUnion('scope', [
62
+ z.object({id: z.string().uuid(), scope: z.literal('workspace'), workspace_id: z.string().uuid()}),
63
+ z.object({id: z.string().uuid(), scope: z.literal('installation')}),
64
+ ]);
63
65
 
64
66
  export type ProvisionerIdentityResponseDto = z.infer<typeof provisionerIdentityResponseSchema>;
@@ -1,30 +1,30 @@
1
1
  import {
2
- MAX_OBSERVED_PROVISIONED_RUNNER_ID_LENGTH,
2
+ MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH,
3
3
  MAX_RECONCILE_OBSERVED_RUNNERS,
4
- reconcileProvisionedRunnersBodySchema,
5
- reconcileProvisionedRunnersResponseSchema,
6
- } from './reconcile-provisioned-runners.js';
4
+ reconcileRunnerInstancesBodySchema,
5
+ reconcileRunnerInstancesResponseSchema,
6
+ } from './reconcile-runner-instances.js';
7
7
 
8
- describe('reconcileProvisionedRunnersBodySchema', () => {
8
+ describe('reconcileRunnerInstancesBodySchema', () => {
9
9
  it('accepts observed provisioned runner ids', () => {
10
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
11
- observed_provisioned_runner_ids: ['01JPROVISIONEDRUNNER000001'],
10
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
11
+ observed_provider_runner_ids: ['01JPROVISIONEDRUNNER000001'],
12
12
  });
13
13
 
14
14
  expect(result.success).toBe(true);
15
15
  });
16
16
 
17
17
  it('accepts an empty observed set', () => {
18
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
19
- observed_provisioned_runner_ids: [],
18
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
19
+ observed_provider_runner_ids: [],
20
20
  });
21
21
 
22
22
  expect(result.success).toBe(true);
23
23
  });
24
24
 
25
25
  it('rejects observed sets above the reconcile limit', () => {
26
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
27
- observed_provisioned_runner_ids: Array.from(
26
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
27
+ observed_provider_runner_ids: Array.from(
28
28
  {length: MAX_RECONCILE_OBSERVED_RUNNERS + 1},
29
29
  (_, index) => `runner-${index}`,
30
30
  ),
@@ -34,24 +34,24 @@ describe('reconcileProvisionedRunnersBodySchema', () => {
34
34
  });
35
35
 
36
36
  it('rejects over-length provisioned runner ids', () => {
37
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
38
- observed_provisioned_runner_ids: ['a'.repeat(MAX_OBSERVED_PROVISIONED_RUNNER_ID_LENGTH + 1)],
37
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
38
+ observed_provider_runner_ids: ['a'.repeat(MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH + 1)],
39
39
  });
40
40
 
41
41
  expect(result.success).toBe(false);
42
42
  });
43
43
 
44
44
  it('rejects duplicate provisioned runner ids', () => {
45
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
46
- observed_provisioned_runner_ids: ['provisioned-runner-1', 'provisioned-runner-1'],
45
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
46
+ observed_provider_runner_ids: ['provisioned-runner-1', 'provisioned-runner-1'],
47
47
  });
48
48
 
49
49
  expect(result.success).toBe(false);
50
50
  });
51
51
 
52
52
  it('rejects extra fields', () => {
53
- const result = reconcileProvisionedRunnersBodySchema.safeParse({
54
- observed_provisioned_runner_ids: [],
53
+ const result = reconcileRunnerInstancesBodySchema.safeParse({
54
+ observed_provider_runner_ids: [],
55
55
  provisioner_hostname: 'worker-1',
56
56
  });
57
57
 
@@ -59,12 +59,12 @@ describe('reconcileProvisionedRunnersBodySchema', () => {
59
59
  });
60
60
  });
61
61
 
62
- describe('reconcileProvisionedRunnersResponseSchema', () => {
62
+ describe('reconcileRunnerInstancesResponseSchema', () => {
63
63
  it('parses reconciled provisioned runner responses', () => {
64
- const result = reconcileProvisionedRunnersResponseSchema.safeParse({
64
+ const result = reconcileRunnerInstancesResponseSchema.safeParse({
65
65
  runners: [
66
66
  {
67
- provisioned_runner_id: 'provisioned-runner-1',
67
+ provider_runner_id: 'provisioned-runner-1',
68
68
  state: 'running',
69
69
  reservation_id: crypto.randomUUID(),
70
70
  runner_session_id: crypto.randomUUID(),
@@ -77,7 +77,7 @@ describe('reconcileProvisionedRunnersResponseSchema', () => {
77
77
  desired_intent: 'keep',
78
78
  },
79
79
  ],
80
- terminated_absent_provisioned_runner_ids: ['provisioned-runner-2'],
80
+ terminated_absent_provider_runner_ids: ['provisioned-runner-2'],
81
81
  });
82
82
 
83
83
  expect(result.success).toBe(true);
@@ -0,0 +1,58 @@
1
+ import {z} from 'zod';
2
+ import {providerRunnerStateSchema} from './report-runner-instances.js';
3
+
4
+ export const MAX_RECONCILE_OBSERVED_RUNNERS = 5000;
5
+ export const MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH = 255;
6
+
7
+ export const reconcileRunnerInstancesBodySchema = z
8
+ .object({
9
+ observed_provider_runner_ids: z
10
+ .array(z.string().min(1).max(MAX_OBSERVED_PROVIDER_RUNNER_ID_LENGTH))
11
+ .max(MAX_RECONCILE_OBSERVED_RUNNERS),
12
+ })
13
+ .strict()
14
+ .refine(
15
+ (body) =>
16
+ new Set(body.observed_provider_runner_ids).size === body.observed_provider_runner_ids.length,
17
+ {
18
+ message: 'observed_provider_runner_ids values must be unique',
19
+ path: ['observed_provider_runner_ids'],
20
+ },
21
+ );
22
+
23
+ export const reconcileDesiredIntentSchema = z.enum(['keep', 'terminate']);
24
+
25
+ export const reconciledBoundJobSchema = z
26
+ .object({
27
+ job_id: z.string().uuid(),
28
+ workflow_run_attempt_id: z.string().uuid(),
29
+ last_heartbeat_at: z.string().datetime(),
30
+ cancellation_requested_at: z.string().datetime().nullable(),
31
+ })
32
+ .strict();
33
+
34
+ export const reconciledRunnerInstanceSchema = z
35
+ .object({
36
+ provider_runner_id: z.string(),
37
+ state: providerRunnerStateSchema.nullable(),
38
+ reservation_id: z.string().uuid().nullable(),
39
+ runner_session_id: z.string().uuid().nullable(),
40
+ bound_job: reconciledBoundJobSchema.nullable(),
41
+ desired_intent: reconcileDesiredIntentSchema,
42
+ })
43
+ .strict();
44
+
45
+ export const reconcileRunnerInstancesResponseSchema = z
46
+ .object({
47
+ runners: z.array(reconciledRunnerInstanceSchema),
48
+ terminated_absent_provider_runner_ids: z.array(z.string()),
49
+ })
50
+ .strict();
51
+
52
+ export type ReconcileRunnerInstancesBodyDto = z.infer<typeof reconcileRunnerInstancesBodySchema>;
53
+ export type ReconcileDesiredIntentDto = z.infer<typeof reconcileDesiredIntentSchema>;
54
+ export type ReconciledBoundJobDto = z.infer<typeof reconciledBoundJobSchema>;
55
+ export type ReconciledRunnerInstanceDto = z.infer<typeof reconciledRunnerInstanceSchema>;
56
+ export type ReconcileRunnerInstancesResponseDto = z.infer<
57
+ typeof reconcileRunnerInstancesResponseSchema
58
+ >;
@@ -20,7 +20,7 @@ export const registerRunnerBodySchema = z.object({
20
20
  export const registerRunnerResponseSchema = z.object({
21
21
  session_token: z.string().min(1),
22
22
  session_id: z.string().uuid(),
23
- mode: z.enum(['manual', 'ephemeral']),
23
+ mode: z.enum(['manual', 'ephemeral', 'activation']),
24
24
  max_claims: z.number().int().positive().nullable(),
25
25
  });
26
26