@tokenfactory/acc-runner 0.44.8 → 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 (174) 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 +10 -1
  28. package/dist/engines/codex-chat.d.ts.map +1 -1
  29. package/dist/engines/codex-chat.js +32 -2
  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 +6 -10
  35. package/dist/machine-console/index.d.ts.map +1 -1
  36. package/dist/machine-console/index.js +61 -54
  37. package/dist/machine-console/index.js.map +1 -1
  38. package/dist/machine-console/transport.d.ts +57 -0
  39. package/dist/machine-console/transport.d.ts.map +1 -0
  40. package/dist/machine-console/transport.js +170 -0
  41. package/dist/machine-console/transport.js.map +1 -0
  42. package/dist/preview-environments/control-plane.d.ts +11 -0
  43. package/dist/preview-environments/control-plane.d.ts.map +1 -0
  44. package/dist/preview-environments/control-plane.js +49 -0
  45. package/dist/preview-environments/control-plane.js.map +1 -0
  46. package/dist/preview-environments/http-provider.d.ts +13 -0
  47. package/dist/preview-environments/http-provider.d.ts.map +1 -0
  48. package/dist/preview-environments/http-provider.js +64 -0
  49. package/dist/preview-environments/http-provider.js.map +1 -0
  50. package/dist/preview-environments/profiles.d.ts +6 -0
  51. package/dist/preview-environments/profiles.d.ts.map +1 -0
  52. package/dist/preview-environments/profiles.js +34 -0
  53. package/dist/preview-environments/profiles.js.map +1 -0
  54. package/dist/preview-environments/safety.d.ts +7 -0
  55. package/dist/preview-environments/safety.d.ts.map +1 -0
  56. package/dist/preview-environments/safety.js +47 -0
  57. package/dist/preview-environments/safety.js.map +1 -0
  58. package/dist/preview-environments/service.d.ts +36 -0
  59. package/dist/preview-environments/service.d.ts.map +1 -0
  60. package/dist/preview-environments/service.js +149 -0
  61. package/dist/preview-environments/service.js.map +1 -0
  62. package/dist/preview-environments/types.d.ts +60 -0
  63. package/dist/preview-environments/types.d.ts.map +1 -0
  64. package/dist/preview-environments/types.js +2 -0
  65. package/dist/preview-environments/types.js.map +1 -0
  66. package/dist/production-migrations/command.d.ts +3 -0
  67. package/dist/production-migrations/command.d.ts.map +1 -0
  68. package/dist/production-migrations/command.js +21 -0
  69. package/dist/production-migrations/command.js.map +1 -0
  70. package/dist/production-migrations/executor.d.ts +59 -0
  71. package/dist/production-migrations/executor.d.ts.map +1 -0
  72. package/dist/production-migrations/executor.js +161 -0
  73. package/dist/production-migrations/executor.js.map +1 -0
  74. package/dist/production-migrations/pg-target.d.ts +22 -0
  75. package/dist/production-migrations/pg-target.d.ts.map +1 -0
  76. package/dist/production-migrations/pg-target.js +87 -0
  77. package/dist/production-migrations/pg-target.js.map +1 -0
  78. package/dist/production-migrations/profiles.d.ts +5 -0
  79. package/dist/production-migrations/profiles.d.ts.map +1 -0
  80. package/dist/production-migrations/profiles.js +39 -0
  81. package/dist/production-migrations/profiles.js.map +1 -0
  82. package/dist/production-migrations/service.d.ts +39 -0
  83. package/dist/production-migrations/service.d.ts.map +1 -0
  84. package/dist/production-migrations/service.js +166 -0
  85. package/dist/production-migrations/service.js.map +1 -0
  86. package/dist/program.d.ts.map +1 -1
  87. package/dist/program.js +17 -0
  88. package/dist/program.js.map +1 -1
  89. package/dist/runtime/worktree.d.ts.map +1 -1
  90. package/dist/runtime/worktree.js +23 -1
  91. package/dist/runtime/worktree.js.map +1 -1
  92. package/dist/secure-execution/auto-lease.d.ts +57 -0
  93. package/dist/secure-execution/auto-lease.d.ts.map +1 -0
  94. package/dist/secure-execution/auto-lease.js +116 -0
  95. package/dist/secure-execution/auto-lease.js.map +1 -0
  96. package/dist/secure-execution/command-policy.d.ts +5 -0
  97. package/dist/secure-execution/command-policy.d.ts.map +1 -0
  98. package/dist/secure-execution/command-policy.js +95 -0
  99. package/dist/secure-execution/command-policy.js.map +1 -0
  100. package/dist/secure-execution/confinement.d.ts +3 -0
  101. package/dist/secure-execution/confinement.d.ts.map +1 -0
  102. package/dist/secure-execution/confinement.js +18 -0
  103. package/dist/secure-execution/confinement.js.map +1 -0
  104. package/dist/secure-execution/engine.d.ts +24 -0
  105. package/dist/secure-execution/engine.d.ts.map +1 -0
  106. package/dist/secure-execution/engine.js +272 -0
  107. package/dist/secure-execution/engine.js.map +1 -0
  108. package/dist/secure-execution/index.d.ts +7 -0
  109. package/dist/secure-execution/index.d.ts.map +1 -0
  110. package/dist/secure-execution/index.js +6 -0
  111. package/dist/secure-execution/index.js.map +1 -0
  112. package/dist/secure-execution/node-pty.d.ts +11 -0
  113. package/dist/secure-execution/node-pty.d.ts.map +1 -0
  114. package/dist/secure-execution/node-pty.js +27 -0
  115. package/dist/secure-execution/node-pty.js.map +1 -0
  116. package/dist/secure-execution/types.d.ts +176 -0
  117. package/dist/secure-execution/types.d.ts.map +1 -0
  118. package/dist/secure-execution/types.js +2 -0
  119. package/dist/secure-execution/types.js.map +1 -0
  120. package/dist/staging-migrations/command.d.ts +2 -0
  121. package/dist/staging-migrations/command.d.ts.map +1 -0
  122. package/dist/staging-migrations/command.js +58 -0
  123. package/dist/staging-migrations/command.js.map +1 -0
  124. package/dist/staging-migrations/executor.d.ts +49 -0
  125. package/dist/staging-migrations/executor.d.ts.map +1 -0
  126. package/dist/staging-migrations/executor.js +125 -0
  127. package/dist/staging-migrations/executor.js.map +1 -0
  128. package/dist/staging-migrations/pg-target.d.ts +20 -0
  129. package/dist/staging-migrations/pg-target.d.ts.map +1 -0
  130. package/dist/staging-migrations/pg-target.js +63 -0
  131. package/dist/staging-migrations/pg-target.js.map +1 -0
  132. package/dist/staging-migrations/profiles.d.ts +5 -0
  133. package/dist/staging-migrations/profiles.d.ts.map +1 -0
  134. package/dist/staging-migrations/profiles.js +31 -0
  135. package/dist/staging-migrations/profiles.js.map +1 -0
  136. package/dist/staging-migrations/service.d.ts +40 -0
  137. package/dist/staging-migrations/service.d.ts.map +1 -0
  138. package/dist/staging-migrations/service.js +157 -0
  139. package/dist/staging-migrations/service.js.map +1 -0
  140. package/dist/supervisor.d.ts +15 -0
  141. package/dist/supervisor.d.ts.map +1 -0
  142. package/dist/supervisor.js +54 -0
  143. package/dist/supervisor.js.map +1 -0
  144. package/dist/terminal/http-carrier.d.ts +17 -0
  145. package/dist/terminal/http-carrier.d.ts.map +1 -0
  146. package/dist/terminal/http-carrier.js +39 -0
  147. package/dist/terminal/http-carrier.js.map +1 -0
  148. package/dist/terminal/pty-adapter.d.ts +88 -0
  149. package/dist/terminal/pty-adapter.d.ts.map +1 -0
  150. package/dist/terminal/pty-adapter.js +252 -0
  151. package/dist/terminal/pty-adapter.js.map +1 -0
  152. package/dist/terminal/transport-contract.d.ts +115 -0
  153. package/dist/terminal/transport-contract.d.ts.map +1 -0
  154. package/dist/terminal/transport-contract.js +2 -0
  155. package/dist/terminal/transport-contract.js.map +1 -0
  156. package/dist/terminal/transport.d.ts +32 -0
  157. package/dist/terminal/transport.d.ts.map +1 -0
  158. package/dist/terminal/transport.js +208 -0
  159. package/dist/terminal/transport.js.map +1 -0
  160. package/dist/watch-chat/wire.d.ts.map +1 -1
  161. package/dist/watch-chat/wire.js +14 -1
  162. package/dist/watch-chat/wire.js.map +1 -1
  163. package/dist/watch.d.ts.map +1 -1
  164. package/dist/watch.js +32 -0
  165. package/dist/watch.js.map +1 -1
  166. package/package.json +6 -1
  167. package/scripts/com.tokenfactory.acc-runner-dedicated.plist +64 -0
  168. package/scripts/com.tokenfactory.acc-runner.plist +90 -0
  169. package/scripts/gen-build-info.d.mts +3 -0
  170. package/scripts/gen-build-info.mjs +72 -0
  171. package/scripts/install-launchd.sh +235 -0
  172. package/scripts/setup-dedicated-runner-darwin.sh +75 -0
  173. package/scripts/setup-dedicated-runner-linux.sh +173 -0
  174. package/scripts/uninstall-launchd.sh +67 -0
@@ -0,0 +1,59 @@
1
+ export declare const PRODUCTION_PROJECT_REF = "ctknjrtevjrzwpuojghx";
2
+ export interface ProductionMigrationItem {
3
+ ordinal: number;
4
+ seq: string;
5
+ slug: string;
6
+ path: string;
7
+ sha: string;
8
+ staging_status: "applied" | "skipped";
9
+ status: "pending" | "skipped" | "applied" | "failed";
10
+ }
11
+ export interface ProductionMigrationPromotion {
12
+ id: string;
13
+ repo: string;
14
+ commit_sha: string;
15
+ plan_hash: string;
16
+ production_project_ref: string;
17
+ production_credential_profile_ref: string;
18
+ staging_ledger_snapshot_sha: string;
19
+ analyzer_classification: "safe" | "review_required" | "blocked";
20
+ items: ProductionMigrationItem[];
21
+ }
22
+ export interface ProductionTarget {
23
+ projectRef(): Promise<string>;
24
+ tryAdvisoryLock(key: string): Promise<boolean>;
25
+ unlockAdvisory(key: string): Promise<void>;
26
+ ledgerHead(): Promise<string | null>;
27
+ ledger(seq: string): Promise<{
28
+ slug: string;
29
+ sha: string;
30
+ } | null>;
31
+ applyFile(file: string, signal: AbortSignal): Promise<void>;
32
+ }
33
+ export interface SignedReceipt {
34
+ receiptId: string;
35
+ digest: string;
36
+ signature: string;
37
+ keyId: string;
38
+ }
39
+ export interface ProductionReceiptSink {
40
+ item(ordinal: number, status: "skipped" | "applied" | "failed", errorCode?: string): Promise<{
41
+ receipt_id: string;
42
+ }>;
43
+ complete(succeeded: boolean, failureCode?: string): Promise<{
44
+ receipt_id: string;
45
+ }>;
46
+ signed(receipt: SignedReceipt): Promise<void>;
47
+ }
48
+ export interface ProductionExecutionOptions {
49
+ timeoutMs?: number;
50
+ cancelled?: () => Promise<boolean>;
51
+ receiptKey: string;
52
+ receiptKeyId: string;
53
+ }
54
+ export declare function productionLedgerSnapshot(items: ProductionMigrationItem[]): string;
55
+ export declare function signReceipt(promotionId: string, action: string, receiptId: string, key: string, keyId: string): SignedReceipt;
56
+ export declare function verifySignedReceipt(receipt: SignedReceipt, key: string): boolean;
57
+ /** Exact-file, fail-closed production executor. Applied ledger rows make crash recovery idempotent. */
58
+ export declare function executeProductionPromotion(promotion: ProductionMigrationPromotion, repoRoot: string, target: ProductionTarget, receipts: ProductionReceiptSink, options: ProductionExecutionOptions): Promise<void>;
59
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/production-migrations/executor.ts"],"names":[],"mappings":"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"}
@@ -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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"}