@tokenfactory/acc-runner 0.44.7 → 0.44.9

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 (187) hide show
  1. package/README.md +38 -0
  2. package/dist/attachments/codex-stage.d.ts +11 -0
  3. package/dist/attachments/codex-stage.d.ts.map +1 -0
  4. package/dist/attachments/codex-stage.js +82 -0
  5. package/dist/attachments/codex-stage.js.map +1 -0
  6. package/dist/attachments/fetch-attachment.d.ts +17 -0
  7. package/dist/attachments/fetch-attachment.d.ts.map +1 -1
  8. package/dist/attachments/fetch-attachment.js +134 -6
  9. package/dist/attachments/fetch-attachment.js.map +1 -1
  10. package/dist/attachments/index.d.ts +2 -1
  11. package/dist/attachments/index.d.ts.map +1 -1
  12. package/dist/attachments/index.js +2 -1
  13. package/dist/attachments/index.js.map +1 -1
  14. package/dist/build-info.generated.d.ts +1 -1
  15. package/dist/build-info.generated.js +2 -2
  16. package/dist/commit-sha.d.ts +31 -0
  17. package/dist/commit-sha.d.ts.map +1 -0
  18. package/dist/commit-sha.js +31 -0
  19. package/dist/commit-sha.js.map +1 -0
  20. package/dist/companion-run.d.ts.map +1 -1
  21. package/dist/companion-run.js +14 -1
  22. package/dist/companion-run.js.map +1 -1
  23. package/dist/doctor.d.ts +16 -0
  24. package/dist/doctor.d.ts.map +1 -1
  25. package/dist/doctor.js +107 -0
  26. package/dist/doctor.js.map +1 -1
  27. package/dist/engines/codex-chat.d.ts +24 -4
  28. package/dist/engines/codex-chat.d.ts.map +1 -1
  29. package/dist/engines/codex-chat.js +102 -20
  30. package/dist/engines/codex-chat.js.map +1 -1
  31. package/dist/login.d.ts.map +1 -1
  32. package/dist/login.js +7 -1
  33. package/dist/login.js.map +1 -1
  34. package/dist/machine-console/index.d.ts +37 -0
  35. package/dist/machine-console/index.d.ts.map +1 -0
  36. package/dist/machine-console/index.js +263 -0
  37. package/dist/machine-console/index.js.map +1 -0
  38. package/dist/machine-console/policy.d.ts +16 -0
  39. package/dist/machine-console/policy.d.ts.map +1 -0
  40. package/dist/machine-console/policy.js +83 -0
  41. package/dist/machine-console/policy.js.map +1 -0
  42. package/dist/machine-console/redact.d.ts +12 -0
  43. package/dist/machine-console/redact.d.ts.map +1 -0
  44. package/dist/machine-console/redact.js +48 -0
  45. package/dist/machine-console/redact.js.map +1 -0
  46. package/dist/machine-console/transport.d.ts +57 -0
  47. package/dist/machine-console/transport.d.ts.map +1 -0
  48. package/dist/machine-console/transport.js +170 -0
  49. package/dist/machine-console/transport.js.map +1 -0
  50. package/dist/mcp-spawn.d.ts +2 -1
  51. package/dist/mcp-spawn.d.ts.map +1 -1
  52. package/dist/mcp-spawn.js +2 -2
  53. package/dist/mcp-spawn.js.map +1 -1
  54. package/dist/preview-environments/control-plane.d.ts +11 -0
  55. package/dist/preview-environments/control-plane.d.ts.map +1 -0
  56. package/dist/preview-environments/control-plane.js +49 -0
  57. package/dist/preview-environments/control-plane.js.map +1 -0
  58. package/dist/preview-environments/http-provider.d.ts +13 -0
  59. package/dist/preview-environments/http-provider.d.ts.map +1 -0
  60. package/dist/preview-environments/http-provider.js +64 -0
  61. package/dist/preview-environments/http-provider.js.map +1 -0
  62. package/dist/preview-environments/profiles.d.ts +6 -0
  63. package/dist/preview-environments/profiles.d.ts.map +1 -0
  64. package/dist/preview-environments/profiles.js +34 -0
  65. package/dist/preview-environments/profiles.js.map +1 -0
  66. package/dist/preview-environments/safety.d.ts +7 -0
  67. package/dist/preview-environments/safety.d.ts.map +1 -0
  68. package/dist/preview-environments/safety.js +47 -0
  69. package/dist/preview-environments/safety.js.map +1 -0
  70. package/dist/preview-environments/service.d.ts +36 -0
  71. package/dist/preview-environments/service.d.ts.map +1 -0
  72. package/dist/preview-environments/service.js +149 -0
  73. package/dist/preview-environments/service.js.map +1 -0
  74. package/dist/preview-environments/types.d.ts +60 -0
  75. package/dist/preview-environments/types.d.ts.map +1 -0
  76. package/dist/preview-environments/types.js +2 -0
  77. package/dist/preview-environments/types.js.map +1 -0
  78. package/dist/production-migrations/command.d.ts +3 -0
  79. package/dist/production-migrations/command.d.ts.map +1 -0
  80. package/dist/production-migrations/command.js +21 -0
  81. package/dist/production-migrations/command.js.map +1 -0
  82. package/dist/production-migrations/executor.d.ts +59 -0
  83. package/dist/production-migrations/executor.d.ts.map +1 -0
  84. package/dist/production-migrations/executor.js +161 -0
  85. package/dist/production-migrations/executor.js.map +1 -0
  86. package/dist/production-migrations/pg-target.d.ts +22 -0
  87. package/dist/production-migrations/pg-target.d.ts.map +1 -0
  88. package/dist/production-migrations/pg-target.js +87 -0
  89. package/dist/production-migrations/pg-target.js.map +1 -0
  90. package/dist/production-migrations/profiles.d.ts +5 -0
  91. package/dist/production-migrations/profiles.d.ts.map +1 -0
  92. package/dist/production-migrations/profiles.js +39 -0
  93. package/dist/production-migrations/profiles.js.map +1 -0
  94. package/dist/production-migrations/service.d.ts +39 -0
  95. package/dist/production-migrations/service.d.ts.map +1 -0
  96. package/dist/production-migrations/service.js +166 -0
  97. package/dist/production-migrations/service.js.map +1 -0
  98. package/dist/program.d.ts.map +1 -1
  99. package/dist/program.js +17 -0
  100. package/dist/program.js.map +1 -1
  101. package/dist/runtime/worktree.d.ts.map +1 -1
  102. package/dist/runtime/worktree.js +23 -1
  103. package/dist/runtime/worktree.js.map +1 -1
  104. package/dist/secure-execution/auto-lease.d.ts +57 -0
  105. package/dist/secure-execution/auto-lease.d.ts.map +1 -0
  106. package/dist/secure-execution/auto-lease.js +116 -0
  107. package/dist/secure-execution/auto-lease.js.map +1 -0
  108. package/dist/secure-execution/command-policy.d.ts +5 -0
  109. package/dist/secure-execution/command-policy.d.ts.map +1 -0
  110. package/dist/secure-execution/command-policy.js +95 -0
  111. package/dist/secure-execution/command-policy.js.map +1 -0
  112. package/dist/secure-execution/confinement.d.ts +3 -0
  113. package/dist/secure-execution/confinement.d.ts.map +1 -0
  114. package/dist/secure-execution/confinement.js +18 -0
  115. package/dist/secure-execution/confinement.js.map +1 -0
  116. package/dist/secure-execution/engine.d.ts +24 -0
  117. package/dist/secure-execution/engine.d.ts.map +1 -0
  118. package/dist/secure-execution/engine.js +272 -0
  119. package/dist/secure-execution/engine.js.map +1 -0
  120. package/dist/secure-execution/index.d.ts +7 -0
  121. package/dist/secure-execution/index.d.ts.map +1 -0
  122. package/dist/secure-execution/index.js +6 -0
  123. package/dist/secure-execution/index.js.map +1 -0
  124. package/dist/secure-execution/node-pty.d.ts +11 -0
  125. package/dist/secure-execution/node-pty.d.ts.map +1 -0
  126. package/dist/secure-execution/node-pty.js +27 -0
  127. package/dist/secure-execution/node-pty.js.map +1 -0
  128. package/dist/secure-execution/types.d.ts +176 -0
  129. package/dist/secure-execution/types.d.ts.map +1 -0
  130. package/dist/secure-execution/types.js +2 -0
  131. package/dist/secure-execution/types.js.map +1 -0
  132. package/dist/staging-migrations/command.d.ts +2 -0
  133. package/dist/staging-migrations/command.d.ts.map +1 -0
  134. package/dist/staging-migrations/command.js +58 -0
  135. package/dist/staging-migrations/command.js.map +1 -0
  136. package/dist/staging-migrations/executor.d.ts +49 -0
  137. package/dist/staging-migrations/executor.d.ts.map +1 -0
  138. package/dist/staging-migrations/executor.js +125 -0
  139. package/dist/staging-migrations/executor.js.map +1 -0
  140. package/dist/staging-migrations/pg-target.d.ts +20 -0
  141. package/dist/staging-migrations/pg-target.d.ts.map +1 -0
  142. package/dist/staging-migrations/pg-target.js +63 -0
  143. package/dist/staging-migrations/pg-target.js.map +1 -0
  144. package/dist/staging-migrations/profiles.d.ts +5 -0
  145. package/dist/staging-migrations/profiles.d.ts.map +1 -0
  146. package/dist/staging-migrations/profiles.js +31 -0
  147. package/dist/staging-migrations/profiles.js.map +1 -0
  148. package/dist/staging-migrations/service.d.ts +40 -0
  149. package/dist/staging-migrations/service.d.ts.map +1 -0
  150. package/dist/staging-migrations/service.js +157 -0
  151. package/dist/staging-migrations/service.js.map +1 -0
  152. package/dist/supervisor.d.ts +15 -0
  153. package/dist/supervisor.d.ts.map +1 -0
  154. package/dist/supervisor.js +54 -0
  155. package/dist/supervisor.js.map +1 -0
  156. package/dist/terminal/http-carrier.d.ts +17 -0
  157. package/dist/terminal/http-carrier.d.ts.map +1 -0
  158. package/dist/terminal/http-carrier.js +39 -0
  159. package/dist/terminal/http-carrier.js.map +1 -0
  160. package/dist/terminal/pty-adapter.d.ts +88 -0
  161. package/dist/terminal/pty-adapter.d.ts.map +1 -0
  162. package/dist/terminal/pty-adapter.js +252 -0
  163. package/dist/terminal/pty-adapter.js.map +1 -0
  164. package/dist/terminal/transport-contract.d.ts +115 -0
  165. package/dist/terminal/transport-contract.d.ts.map +1 -0
  166. package/dist/terminal/transport-contract.js +2 -0
  167. package/dist/terminal/transport-contract.js.map +1 -0
  168. package/dist/terminal/transport.d.ts +32 -0
  169. package/dist/terminal/transport.d.ts.map +1 -0
  170. package/dist/terminal/transport.js +208 -0
  171. package/dist/terminal/transport.js.map +1 -0
  172. package/dist/watch-chat/wire.d.ts.map +1 -1
  173. package/dist/watch-chat/wire.js +14 -1
  174. package/dist/watch-chat/wire.js.map +1 -1
  175. package/dist/watch.d.ts +3 -0
  176. package/dist/watch.d.ts.map +1 -1
  177. package/dist/watch.js +57 -0
  178. package/dist/watch.js.map +1 -1
  179. package/package.json +6 -1
  180. package/scripts/com.tokenfactory.acc-runner-dedicated.plist +64 -0
  181. package/scripts/com.tokenfactory.acc-runner.plist +90 -0
  182. package/scripts/gen-build-info.d.mts +3 -0
  183. package/scripts/gen-build-info.mjs +72 -0
  184. package/scripts/install-launchd.sh +235 -0
  185. package/scripts/setup-dedicated-runner-darwin.sh +75 -0
  186. package/scripts/setup-dedicated-runner-linux.sh +173 -0
  187. package/scripts/uninstall-launchd.sh +67 -0
@@ -0,0 +1,161 @@
1
+ import { createHash, createHmac, timingSafeEqual } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { isCommitSha, isSha256Digest } from "../commit-sha.js";
5
+ export const PRODUCTION_PROJECT_REF = "ctknjrtevjrzwpuojghx";
6
+ export function productionLedgerSnapshot(items) {
7
+ const value = items
8
+ .map((item) => `${item.ordinal}:${item.seq}:${item.slug}:${item.sha}:${item.staging_status}`)
9
+ .join("|");
10
+ return createHash("sha256").update(value).digest("hex");
11
+ }
12
+ export function signReceipt(promotionId, action, receiptId, key, keyId) {
13
+ if (key.length < 32 || !keyId)
14
+ throw new Error("production_receipt_signing_key_required");
15
+ const digest = createHash("sha256").update(`${promotionId}:${action}:${receiptId}`).digest("hex");
16
+ return {
17
+ receiptId,
18
+ digest,
19
+ signature: createHmac("sha256", key).update(digest).digest("hex"),
20
+ keyId,
21
+ };
22
+ }
23
+ export function verifySignedReceipt(receipt, key) {
24
+ const actual = Buffer.from(receipt.signature, "hex");
25
+ const expected = Buffer.from(createHmac("sha256", key).update(receipt.digest).digest("hex"), "hex");
26
+ return actual.length === expected.length && timingSafeEqual(actual, expected);
27
+ }
28
+ function assertPromotion(promotion) {
29
+ if (promotion.production_project_ref !== PRODUCTION_PROJECT_REF)
30
+ throw new Error("production_project_pin_invalid");
31
+ if (promotion.analyzer_classification !== "safe")
32
+ throw new Error("production_analyzer_not_safe");
33
+ if (!isCommitSha(promotion.commit_sha))
34
+ throw new Error("production_commit_invalid");
35
+ if (!isSha256Digest(promotion.plan_hash))
36
+ throw new Error("production_plan_hash_invalid");
37
+ if (promotion.items.length === 0)
38
+ throw new Error("production_plan_empty");
39
+ if (productionLedgerSnapshot(promotion.items) !== promotion.staging_ledger_snapshot_sha)
40
+ throw new Error("production_staging_snapshot_mismatch");
41
+ let previous = null;
42
+ for (const [index, item] of promotion.items.entries()) {
43
+ if (item.ordinal !== index ||
44
+ item.path !== `supabase/migrations/${item.seq}_${item.slug}.sql` ||
45
+ !/^[0-9]{4}$/.test(item.seq) ||
46
+ !isSha256Digest(item.sha))
47
+ throw new Error("production_plan_item_invalid");
48
+ if (previous !== null && Number(item.seq) !== previous + 1)
49
+ throw new Error("production_plan_not_contiguous");
50
+ previous = Number(item.seq);
51
+ }
52
+ }
53
+ function insideRepo(repoRoot, migrationPath) {
54
+ const root = path.resolve(repoRoot);
55
+ const resolved = path.resolve(root, migrationPath);
56
+ if (!resolved.startsWith(`${root}${path.sep}`))
57
+ throw new Error("production_migration_path_escape");
58
+ return resolved;
59
+ }
60
+ function failureCode(error) {
61
+ const raw = error instanceof Error ? error.message : "production_migration_failed";
62
+ return raw
63
+ .replace(/postgres(?:ql)?:\/\/[^\s]+/gi, "[REDACTED_DB_URL]")
64
+ .replace(/(password|token|secret)=?[^\s]*/gi, "$1=[REDACTED]")
65
+ .replace(/[^a-zA-Z0-9_.:[\] -]/g, "_")
66
+ .slice(0, 200);
67
+ }
68
+ async function signed(promotion, action, result, receipts, options) {
69
+ if (!/^[0-9a-f-]{36}$/i.test(result.receipt_id))
70
+ throw new Error("production_receipt_invalid");
71
+ await receipts.signed(signReceipt(promotion.id, action, result.receipt_id, options.receiptKey, options.receiptKeyId));
72
+ }
73
+ /** Exact-file, fail-closed production executor. Applied ledger rows make crash recovery idempotent. */
74
+ export async function executeProductionPromotion(promotion, repoRoot, target, receipts, options) {
75
+ const lockKey = `acc:production-migrations:${PRODUCTION_PROJECT_REF}`;
76
+ const timeoutMs = Math.max(5_000, Math.min(options.timeoutMs ?? 300_000, 900_000));
77
+ let locked = false;
78
+ try {
79
+ assertPromotion(promotion);
80
+ if ((await target.projectRef()) !== PRODUCTION_PROJECT_REF)
81
+ throw new Error("production_project_pin_mismatch");
82
+ if (!(await target.tryAdvisoryLock(lockKey)))
83
+ throw new Error("production_migration_lock_busy");
84
+ locked = true;
85
+ const head = await target.ledgerHead();
86
+ const acceptable = new Set([
87
+ String(Number(promotion.items[0].seq) - 1).padStart(4, "0"),
88
+ ...promotion.items.map((item) => item.seq),
89
+ ]);
90
+ if (!head || !acceptable.has(head))
91
+ throw new Error("production_ledger_head_mismatch");
92
+ for (const item of promotion.items) {
93
+ if (await options.cancelled?.())
94
+ throw new Error("production_migration_cancelled");
95
+ if (item.status === "applied" || item.status === "skipped")
96
+ continue;
97
+ const existing = await target.ledger(item.seq);
98
+ if (existing) {
99
+ if (existing.slug !== item.slug || existing.sha !== item.sha)
100
+ throw new Error(`production_ledger_drift_${item.seq}`);
101
+ const result = await receipts.item(item.ordinal, "skipped");
102
+ await signed(promotion, `item:${item.ordinal}:skipped`, result, receipts, options);
103
+ continue;
104
+ }
105
+ const file = insideRepo(repoRoot, item.path);
106
+ const sql = await readFile(file);
107
+ if (createHash("sha256").update(sql).digest("hex") !== item.sha)
108
+ throw new Error(`production_file_hash_mismatch_${item.seq}`);
109
+ const controller = new AbortController();
110
+ let cancelled = false;
111
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
112
+ const cancelPoll = options.cancelled
113
+ ? setInterval(() => {
114
+ void options.cancelled?.().then((value) => {
115
+ if (value) {
116
+ cancelled = true;
117
+ controller.abort();
118
+ }
119
+ });
120
+ }, 250)
121
+ : null;
122
+ cancelPoll?.unref?.();
123
+ try {
124
+ await target.applyFile(file, controller.signal);
125
+ const recorded = await target.ledger(item.seq);
126
+ if (!recorded || recorded.slug !== item.slug || recorded.sha !== item.sha)
127
+ throw new Error(`production_ledger_receipt_missing_${item.seq}`);
128
+ const result = await receipts.item(item.ordinal, "applied");
129
+ await signed(promotion, `item:${item.ordinal}:applied`, result, receipts, options);
130
+ }
131
+ catch (error) {
132
+ const code = cancelled
133
+ ? "production_migration_cancelled"
134
+ : controller.signal.aborted
135
+ ? "production_migration_timeout"
136
+ : failureCode(error);
137
+ const result = await receipts.item(item.ordinal, "failed", code);
138
+ await signed(promotion, `item:${item.ordinal}:failed`, result, receipts, options);
139
+ throw new Error(code);
140
+ }
141
+ finally {
142
+ clearTimeout(timer);
143
+ if (cancelPoll)
144
+ clearInterval(cancelPoll);
145
+ }
146
+ }
147
+ const result = await receipts.complete(true);
148
+ await signed(promotion, "complete:succeeded", result, receipts, options);
149
+ }
150
+ catch (error) {
151
+ const result = await receipts.complete(false, failureCode(error)).catch(() => null);
152
+ if (result)
153
+ await signed(promotion, "complete:failed", result, receipts, options).catch(() => undefined);
154
+ throw error;
155
+ }
156
+ finally {
157
+ if (locked)
158
+ await target.unlockAdvisory(lockKey).catch(() => undefined);
159
+ }
160
+ }
161
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/production-migrations/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type ProductionTarget } from "./executor.js";
2
+ export declare function productionCredentialEnvName(profile: string): string;
3
+ export declare function projectRefFromProductionUrl(value: string): string;
4
+ export declare class PgProductionTarget implements ProductionTarget {
5
+ private readonly env;
6
+ private readonly client;
7
+ private readonly connectionString;
8
+ private readonly pinnedRef;
9
+ constructor(profile: string, env?: NodeJS.ProcessEnv);
10
+ connect(): Promise<void>;
11
+ close(): Promise<void>;
12
+ projectRef(): Promise<string>;
13
+ tryAdvisoryLock(key: string): Promise<boolean>;
14
+ unlockAdvisory(key: string): Promise<void>;
15
+ ledger(seq: string): Promise<{
16
+ slug: string;
17
+ sha: string;
18
+ } | null>;
19
+ ledgerHead(): Promise<string | null>;
20
+ applyFile(file: string, signal: AbortSignal): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=pg-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-target.d.ts","sourceRoot":"","sources":["../../src/production-migrations/pg-target.ts"],"names":[],"mappings":"AAGA,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAI9E,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,qBAAa,kBAAmB,YAAW,gBAAgB;IAOvD,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGjC,OAAO,EAAE,MAAM,EACE,GAAG,GAAE,MAAM,CAAC,UAAwB;IAcjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAGxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAGtB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAG7B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO9C,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG1C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAOlE,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAMpC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAmBlE"}
@@ -0,0 +1,87 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { Client } from "pg";
4
+ import { PRODUCTION_PROJECT_REF } from "./executor.js";
5
+ const execFileAsync = promisify(execFile);
6
+ export function productionCredentialEnvName(profile) {
7
+ if (!/^[A-Za-z0-9_.-]{1,80}$/.test(profile))
8
+ throw new Error("production_credential_profile_invalid");
9
+ return `ACC_DB_PROFILE_${profile.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_URL`;
10
+ }
11
+ export function projectRefFromProductionUrl(value) {
12
+ let parsed;
13
+ try {
14
+ parsed = new URL(value);
15
+ }
16
+ catch {
17
+ throw new Error("production_credential_url_invalid");
18
+ }
19
+ const ref = `${parsed.hostname}${parsed.pathname}`.match(/\b([a-z0-9]{20})\b/)?.[1];
20
+ if (!ref)
21
+ throw new Error("production_credential_project_ref_missing");
22
+ return ref;
23
+ }
24
+ export class PgProductionTarget {
25
+ env;
26
+ client;
27
+ connectionString;
28
+ pinnedRef;
29
+ constructor(profile, env = process.env) {
30
+ this.env = env;
31
+ const value = env[productionCredentialEnvName(profile)];
32
+ if (!value)
33
+ throw new Error("production_credential_profile_not_configured");
34
+ this.pinnedRef = projectRefFromProductionUrl(value);
35
+ if (this.pinnedRef !== PRODUCTION_PROJECT_REF)
36
+ throw new Error("non_production_target_forbidden");
37
+ this.connectionString = value;
38
+ this.client = new Client({
39
+ connectionString: value,
40
+ application_name: "acc-production-migration-executor",
41
+ });
42
+ }
43
+ async connect() {
44
+ await this.client.connect();
45
+ }
46
+ async close() {
47
+ await this.client.end();
48
+ }
49
+ async projectRef() {
50
+ return this.pinnedRef;
51
+ }
52
+ async tryAdvisoryLock(key) {
53
+ const result = await this.client.query("select pg_try_advisory_lock(hashtextextended($1, 0)) as locked", [key]);
54
+ return result.rows[0]?.locked === true;
55
+ }
56
+ async unlockAdvisory(key) {
57
+ await this.client.query("select pg_advisory_unlock(hashtextextended($1, 0))", [key]);
58
+ }
59
+ async ledger(seq) {
60
+ const result = await this.client.query("select slug, sha from acc.applied_migrations where seq = $1", [seq]);
61
+ return result.rows[0] ?? null;
62
+ }
63
+ async ledgerHead() {
64
+ const result = await this.client.query("select seq from acc.applied_migrations order by seq::integer desc limit 1");
65
+ return result.rows[0]?.seq ?? null;
66
+ }
67
+ async applyFile(file, signal) {
68
+ // Do not leak the runner/token/signing environment into psql. The opaque
69
+ // profile resolves locally and only the minimum process environment crosses
70
+ // the child boundary; the connection string is never placed in argv.
71
+ const childEnv = {
72
+ PATH: this.env.PATH,
73
+ HOME: this.env.HOME,
74
+ LANG: this.env.LANG,
75
+ LC_ALL: this.env.LC_ALL,
76
+ SSL_CERT_FILE: this.env.SSL_CERT_FILE,
77
+ PGCONNECT_TIMEOUT: this.env.PGCONNECT_TIMEOUT ?? "10",
78
+ PGDATABASE: this.connectionString,
79
+ };
80
+ await execFileAsync("psql", ["-X", "--set", "ON_ERROR_STOP=1", "--file", file], {
81
+ env: childEnv,
82
+ signal,
83
+ maxBuffer: 256 * 1024,
84
+ });
85
+ }
86
+ }
87
+ //# sourceMappingURL=pg-target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-target.js","sourceRoot":"","sources":["../../src/production-migrations/pg-target.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function configuredProductionMigrationProfiles(env?: NodeJS.ProcessEnv): string[];
2
+ export declare function configuredProductionPromotionIds(env?: NodeJS.ProcessEnv): string[];
3
+ export declare function productionMigrationServiceEnabled(env?: NodeJS.ProcessEnv): boolean;
4
+ export declare function productionMigrationCaps(env?: NodeJS.ProcessEnv): Record<string, unknown>;
5
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../src/production-migrations/profiles.ts"],"names":[],"mappings":"AAGA,wBAAgB,qCAAqC,CACnD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAaV;AAED,wBAAgB,gCAAgC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,EAAE,CAS/F;AAED,wBAAgB,iCAAiC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAQ/F;AAED,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIzB"}
@@ -0,0 +1,39 @@
1
+ import { PRODUCTION_PROJECT_REF } from "./executor.js";
2
+ import { projectRefFromProductionUrl } from "./pg-target.js";
3
+ export function configuredProductionMigrationProfiles(env = process.env) {
4
+ const profiles = [];
5
+ for (const [name, value] of Object.entries(env)) {
6
+ const match = /^ACC_DB_PROFILE_([A-Z0-9_]+)_URL$/.exec(name);
7
+ if (!match || !value)
8
+ continue;
9
+ try {
10
+ if (projectRefFromProductionUrl(value) === PRODUCTION_PROJECT_REF)
11
+ profiles.push(match[1].toLowerCase());
12
+ }
13
+ catch {
14
+ /* malformed and non-production credentials are never advertised */
15
+ }
16
+ }
17
+ return profiles.sort();
18
+ }
19
+ export function configuredProductionPromotionIds(env = process.env) {
20
+ return [
21
+ ...new Set((env.ACC_PRODUCTION_MIGRATION_PROMOTION_IDS ?? "")
22
+ .split(",")
23
+ .map((value) => value.trim())
24
+ .filter((value) => /^[0-9a-f-]{36}$/i.test(value))),
25
+ ];
26
+ }
27
+ export function productionMigrationServiceEnabled(env = process.env) {
28
+ return (env.ACC_PRODUCTION_MIGRATION_SERVICE === "1" &&
29
+ configuredProductionMigrationProfiles(env).length > 0 &&
30
+ configuredProductionPromotionIds(env).length > 0 &&
31
+ (env.ACC_PRODUCTION_MIGRATION_RECEIPT_KEY?.length ?? 0) >= 32 &&
32
+ Boolean(env.ACC_PRODUCTION_MIGRATION_RECEIPT_KEY_ID));
33
+ }
34
+ export function productionMigrationCaps(env = process.env) {
35
+ return configuredProductionMigrationProfiles(env).length > 0
36
+ ? { production_migrations: true, production_project_ref: PRODUCTION_PROJECT_REF }
37
+ : {};
38
+ }
39
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/production-migrations/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,UAAU,qCAAqC,CACnD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK;YAAE,SAAS;QAC/B,IAAI,CAAC;YACH,IAAI,2BAA2B,CAAC,KAAK,CAAC,KAAK,sBAAsB;gBAC/D,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,MAAyB,OAAO,CAAC,GAAG;IACnF,OAAO;QACL,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,CAAC,sCAAsC,IAAI,EAAE,CAAC;aAC/C,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;aAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CACrD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpF,OAAO,CACL,GAAG,CAAC,gCAAgC,KAAK,GAAG;QAC5C,qCAAqC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;QACrD,gCAAgC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;QAChD,CAAC,GAAG,CAAC,oCAAoC,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE;QAC7D,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CACrD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,qCAAqC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;QAC1D,CAAC,CAAC,EAAE,qBAAqB,EAAE,IAAI,EAAE,sBAAsB,EAAE,sBAAsB,EAAE;QACjF,CAAC,CAAC,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { RunnerConfig } from "../config.js";
2
+ import type { RunnerSupabaseClient } from "../supabase.js";
3
+ import { type ProductionTarget } from "./executor.js";
4
+ export interface ProductionMigrationLogger {
5
+ info(message: string): void;
6
+ error(message: string): void;
7
+ }
8
+ export interface ProductionMigrationServiceOptions {
9
+ env?: NodeJS.ProcessEnv;
10
+ pollMs?: number;
11
+ logger?: ProductionMigrationLogger;
12
+ resolveRepo?: (repo: string) => string;
13
+ verifyCommit?: (root: string, sha: string) => Promise<void>;
14
+ targetFactory?: (profile: string) => ProductionTarget & {
15
+ connect(): Promise<void>;
16
+ close(): Promise<void>;
17
+ };
18
+ }
19
+ export declare function productionSafeCode(error: unknown): string;
20
+ export declare function verifyProductionCheckout(root: string, sha: string): Promise<void>;
21
+ export declare class ProductionMigrationService {
22
+ private readonly sb;
23
+ private readonly cfg;
24
+ private readonly runnerId;
25
+ private readonly options;
26
+ private timer;
27
+ private active;
28
+ private stopping;
29
+ private readonly env;
30
+ private readonly logger;
31
+ private readonly pollMs;
32
+ constructor(sb: RunnerSupabaseClient, cfg: RunnerConfig, runnerId: string, options?: ProductionMigrationServiceOptions);
33
+ start(): void;
34
+ stop(): Promise<void>;
35
+ pollOnce(): Promise<void>;
36
+ claimAndRun(promotionId: string): Promise<"skipped" | "succeeded" | "failed">;
37
+ }
38
+ export { productionMigrationCaps, productionMigrationServiceEnabled } from "./profiles.js";
39
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/production-migrations/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAIL,KAAK,gBAAgB,EAEtB,MAAM,eAAe,CAAC;AAOvB,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,iCAAiC;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG;QACtD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;KACxB,CAAC;CACH;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOzD;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvF;AAED,qBAAa,0BAA0B;IASnC,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,EAAE,EAAE,oBAAoB,EACxB,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,iCAAsC;IAOlE,KAAK,IAAI,IAAI;IAQP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAezB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CAuFpF;AAED,OAAO,EAAE,uBAAuB,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,166 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { resolveMachineRepoPath } from "../machine-console/index.js";
4
+ import { executeProductionPromotion, } from "./executor.js";
5
+ import { PgProductionTarget } from "./pg-target.js";
6
+ import { configuredProductionPromotionIds } from "./profiles.js";
7
+ import { isCommitSha } from "../commit-sha.js";
8
+ const execFileAsync = promisify(execFile);
9
+ export function productionSafeCode(error) {
10
+ const raw = error instanceof Error ? error.message : "unknown_error";
11
+ return raw
12
+ .replace(/postgres(?:ql)?:\/\/[^\s]+/gi, "[REDACTED_DB_URL]")
13
+ .replace(/(password|token|secret)=?[^\s]*/gi, "$1=[REDACTED]")
14
+ .replace(/[^a-zA-Z0-9_.:[\] -]/g, "_")
15
+ .slice(0, 240);
16
+ }
17
+ export async function verifyProductionCheckout(root, sha) {
18
+ if (!isCommitSha(sha))
19
+ throw new Error("production_commit_invalid");
20
+ const { stdout } = await execFileAsync("git", ["rev-parse", "HEAD"], { cwd: root });
21
+ if (stdout.trim().toLowerCase() !== sha.toLowerCase())
22
+ throw new Error("production_commit_mismatch");
23
+ }
24
+ export class ProductionMigrationService {
25
+ sb;
26
+ cfg;
27
+ runnerId;
28
+ options;
29
+ timer = null;
30
+ active = false;
31
+ stopping = false;
32
+ env;
33
+ logger;
34
+ pollMs;
35
+ constructor(sb, cfg, runnerId, options = {}) {
36
+ this.sb = sb;
37
+ this.cfg = cfg;
38
+ this.runnerId = runnerId;
39
+ this.options = options;
40
+ this.env = options.env ?? process.env;
41
+ this.logger = options.logger ?? console;
42
+ this.pollMs = Math.max(5_000, Math.min(options.pollMs ?? 30_000, 300_000));
43
+ }
44
+ start() {
45
+ if (this.timer)
46
+ return;
47
+ this.stopping = false;
48
+ void this.pollOnce();
49
+ this.timer = setInterval(() => void this.pollOnce(), this.pollMs);
50
+ this.timer.unref?.();
51
+ }
52
+ async stop() {
53
+ this.stopping = true;
54
+ if (this.timer)
55
+ clearInterval(this.timer);
56
+ this.timer = null;
57
+ const deadline = Date.now() + 30_000;
58
+ while (this.active && Date.now() < deadline)
59
+ await new Promise((resolve) => setTimeout(resolve, 25));
60
+ if (this.active)
61
+ this.logger.error("[acc-runner] production migration shutdown_wait_exceeded");
62
+ }
63
+ async pollOnce() {
64
+ if (this.active || this.stopping)
65
+ return;
66
+ this.active = true;
67
+ try {
68
+ for (const promotionId of configuredProductionPromotionIds(this.env)) {
69
+ if (this.stopping)
70
+ break;
71
+ await this.claimAndRun(promotionId);
72
+ }
73
+ }
74
+ catch (error) {
75
+ this.logger.error(`[acc-runner] production migration service: ${productionSafeCode(error)}`);
76
+ }
77
+ finally {
78
+ this.active = false;
79
+ }
80
+ }
81
+ async claimAndRun(promotionId) {
82
+ const claimed = await this.sb.rpc("claim_production_migration_promotion", {
83
+ p_promotion_id: promotionId,
84
+ });
85
+ if (claimed.error) {
86
+ this.logger.info(`[acc-runner] production migration claim skipped: ${productionSafeCode(claimed.error)}`);
87
+ return "skipped";
88
+ }
89
+ const payload = claimed.data;
90
+ if (!payload.promotion ||
91
+ !payload.production_credential_profile_ref ||
92
+ !Array.isArray(payload.items) ||
93
+ !payload.receipt_id)
94
+ throw new Error("invalid_production_claim_receipt");
95
+ const promotion = {
96
+ ...payload.promotion,
97
+ production_credential_profile_ref: payload.production_credential_profile_ref,
98
+ items: payload.items,
99
+ };
100
+ const signed = async (receipt) => {
101
+ const event = await this.sb.rpc("log_activity", {
102
+ p_verb: "production_migration.runner_receipt",
103
+ p_target_id: promotion.id,
104
+ p_target_type: "production_migration_promotion",
105
+ p_payload: { ...receipt, runner_id: this.runnerId },
106
+ });
107
+ if (event.error)
108
+ throw new Error(`production_signed_receipt_failed:${event.error.message}`);
109
+ };
110
+ const receipts = {
111
+ item: async (ordinal, status, errorCode) => {
112
+ const result = await this.sb.rpc("record_production_migration_item", {
113
+ p_promotion_id: promotion.id,
114
+ p_ordinal: ordinal,
115
+ p_status: status,
116
+ p_error_code: errorCode ? productionSafeCode(errorCode) : null,
117
+ });
118
+ if (result.error)
119
+ throw new Error(`production_item_receipt_failed:${result.error.message}`);
120
+ return result.data;
121
+ },
122
+ complete: async (succeeded, failureCode) => {
123
+ const result = await this.sb.rpc("complete_production_migration_promotion", {
124
+ p_promotion_id: promotion.id,
125
+ p_succeeded: succeeded,
126
+ p_failure_code: failureCode ? productionSafeCode(failureCode) : null,
127
+ });
128
+ if (result.error)
129
+ throw new Error(`production_completion_receipt_failed:${result.error.message}`);
130
+ return result.data;
131
+ },
132
+ signed,
133
+ };
134
+ let target = null;
135
+ let started = false;
136
+ try {
137
+ const root = this.options.resolveRepo?.(promotion.repo) ??
138
+ resolveMachineRepoPath(this.cfg, promotion.repo);
139
+ await (this.options.verifyCommit ?? verifyProductionCheckout)(root, promotion.commit_sha);
140
+ target =
141
+ this.options.targetFactory?.(promotion.production_credential_profile_ref) ??
142
+ new PgProductionTarget(promotion.production_credential_profile_ref, this.env);
143
+ await target.connect();
144
+ started = true;
145
+ await executeProductionPromotion(promotion, root, target, receipts, {
146
+ cancelled: async () => this.stopping,
147
+ timeoutMs: Number(this.env.ACC_PRODUCTION_MIGRATION_TIMEOUT_MS ?? 300_000),
148
+ receiptKey: this.env.ACC_PRODUCTION_MIGRATION_RECEIPT_KEY ?? "",
149
+ receiptKeyId: this.env.ACC_PRODUCTION_MIGRATION_RECEIPT_KEY_ID ?? "",
150
+ });
151
+ this.logger.info(`[acc-runner] production migration promotion ${promotion.id} succeeded`);
152
+ return "succeeded";
153
+ }
154
+ catch (error) {
155
+ if (!started)
156
+ await receipts.complete(false, productionSafeCode(error)).catch(() => undefined);
157
+ this.logger.error(`[acc-runner] production migration promotion ${promotion.id}: ${productionSafeCode(error)}`);
158
+ return "failed";
159
+ }
160
+ finally {
161
+ await target?.close().catch(() => undefined);
162
+ }
163
+ }
164
+ }
165
+ export { productionMigrationCaps, productionMigrationServiceEnabled } from "./profiles.js";
166
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/production-migrations/service.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAmC7C,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAmYvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAQvD;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAKjD"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAqC7C,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAqZvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAQvD;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAKjD"}
package/dist/program.js CHANGED
@@ -57,6 +57,8 @@ import { PROTOCOL_VERSION } from "./types.js";
57
57
  import { PACKAGE_VERSION } from "./pkg-version.js";
58
58
  import { LOADED_BUILD_FINGERPRINT, runningBuildStatus } from "./build-fingerprint.js";
59
59
  import { readRunningBuild } from "./runtime/running-build.js";
60
+ import { applyApprovedStagingMigrationCommand } from "./staging-migrations/command.js";
61
+ import { applyApprovedProductionMigrationCommand } from "./production-migrations/command.js";
60
62
  /** RUNNER-NAMED-INSTANCES-1: shared by the four machine-lane commands. */
61
63
  const INSTANCE_FLAG_HELP = `Named runner instance on this host (env: ${INSTANCE_ENV}). ` +
62
64
  "Lowercase letters, digits and dashes. Omit for the default instance.";
@@ -255,6 +257,21 @@ export function buildProgram(options = {}) {
255
257
  const code = await doctorCommand({ strict: opts.strict === true });
256
258
  process.exitCode = code;
257
259
  });
260
+ const migrationsCmd = program
261
+ .command("migrations")
262
+ .description("Execute an exact, approved staging migration plan on this runner.");
263
+ migrationsCmd
264
+ .command("apply-approved")
265
+ .description("Apply repository migration files from an approved ACC plan (staging only).")
266
+ .argument("<plan-id>", "Approved staging migration plan UUID.")
267
+ .option("--instance <name>", INSTANCE_FLAG_HELP)
268
+ .action((planId) => guard(() => applyApprovedStagingMigrationCommand(planId))());
269
+ migrationsCmd
270
+ .command("apply-production")
271
+ .description("Apply an independently approved, production-pinned migration promotion.")
272
+ .argument("<promotion-id>", "Approved production migration promotion UUID.")
273
+ .option("--instance <name>", INSTANCE_FLAG_HELP)
274
+ .action((promotionId) => guard(() => applyApprovedProductionMigrationCommand(promotionId))());
258
275
  // NEEDS-INFO-HALT: a spawned agent that needs clarification / approval /
259
276
  // missing information raises a needs_clarification halt for its task and hands
260
277
  // the question off to JOJO, instead of guessing or dead-lettering. The operator