codex-multi-auth 0.1.4 → 0.1.7

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.
@@ -2,21 +2,17 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width,initial-scale=1" />
6
- <title>OpenAI Codex Callback Received</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Codex Sign-In Complete</title>
7
7
  <style>
8
- /* Space Grotesk import removed to avoid CSP font-src violations; rely on system stack. */
9
-
10
8
  :root {
11
- --bg: #020403;
12
- --bg2: #050908;
13
- --surface: rgba(6, 10, 9, 0.92);
14
- --border: rgba(255, 255, 255, 0.08);
15
- --divider: rgba(255, 255, 255, 0.07);
16
- --text: #f5fbf7;
17
- --muted: rgba(245, 251, 247, 0.68);
18
- --accent: #49f1a8;
19
- --accent-soft: rgba(73, 241, 168, 0.15);
9
+ color-scheme: dark;
10
+ --bg: #0b0b0b;
11
+ --panel: #111111;
12
+ --text: #f2f2f2;
13
+ --muted: #a3a3a3;
14
+ --line: #232323;
15
+ --ok: #7cf0a6;
20
16
  }
21
17
 
22
18
  * {
@@ -26,245 +22,105 @@
26
22
  body {
27
23
  margin: 0;
28
24
  min-height: 100vh;
29
- font-family: "Segoe UI", system-ui, -apple-system, "IBM Plex Sans", sans-serif;
30
- background: radial-gradient(circle at top, rgba(73, 241, 168, 0.12), transparent 55%),
31
- linear-gradient(180deg, var(--bg), var(--bg2));
32
- color: var(--text);
33
25
  display: grid;
34
26
  place-items: center;
35
- padding: 32px 16px;
27
+ background: var(--bg);
28
+ color: var(--text);
29
+ font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
30
+ padding: 24px;
36
31
  }
37
32
 
38
33
  main {
39
- width: min(440px, 100%);
40
- background: var(--surface);
41
- border-radius: 22px;
42
- border: 1px solid var(--border);
43
- padding: 32px;
44
- box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
45
- display: flex;
46
- flex-direction: column;
47
- gap: 18px;
48
- }
49
-
50
- .eyebrow {
51
- font-size: 12px;
52
- text-transform: uppercase;
53
- letter-spacing: 0.22em;
54
- color: var(--muted);
55
- }
56
-
57
- .icon {
58
- width: 64px;
59
- height: 64px;
60
- border-radius: 16px;
61
- border: 1px solid var(--border);
62
- background: var(--accent-soft);
34
+ width: min(520px, 100%);
35
+ background: var(--panel);
36
+ border: 1px solid var(--line);
37
+ border-radius: 12px;
38
+ padding: 20px;
63
39
  display: grid;
64
- place-items: center;
65
- color: var(--accent);
66
- margin: 4px 0 6px;
67
- position: relative;
68
- animation: fade 1s ease both;
69
- }
70
-
71
- .icon::after {
72
- content: "";
73
- width: 20px;
74
- height: 12px;
75
- border-left: 3px solid currentColor;
76
- border-bottom: 3px solid currentColor;
77
- transform: rotate(-45deg);
40
+ gap: 14px;
78
41
  }
79
42
 
80
43
  h1 {
81
44
  margin: 0;
82
- font-size: clamp(26px, 4vw, 32px);
45
+ font-size: 20px;
46
+ font-weight: 600;
83
47
  letter-spacing: -0.02em;
84
48
  }
85
49
 
86
- .lead {
50
+ p {
87
51
  margin: 0;
88
52
  color: var(--muted);
89
- font-size: 15px;
90
- line-height: 1.6;
91
- }
92
-
93
- .state {
94
- display: flex;
95
- align-items: baseline;
96
- justify-content: space-between;
97
- padding: 16px 18px;
98
- border-radius: 16px;
99
- background: rgba(8, 14, 11, 0.75);
100
- border: 1px solid var(--border);
101
- }
102
-
103
- .state span {
104
- font-size: 13px;
105
- text-transform: uppercase;
106
- letter-spacing: 0.15em;
107
- color: var(--muted);
108
- }
109
-
110
- .state strong {
111
- font-size: 20px;
112
- color: var(--accent);
113
- font-weight: 600;
114
- }
115
-
116
- .status-list {
117
- list-style: none;
118
- margin: 8px 0 0;
119
- padding: 0;
120
- display: flex;
121
- flex-direction: column;
122
- gap: 10px;
123
- }
124
-
125
- .status-list li {
126
- display: flex;
127
- align-items: center;
128
- justify-content: space-between;
129
- border-bottom: 1px solid var(--divider);
130
- padding-bottom: 8px;
131
53
  font-size: 14px;
54
+ line-height: 1.5;
132
55
  }
133
56
 
134
- .status-list li:last-child {
135
- border-bottom: none;
136
- padding-bottom: 0;
137
- }
138
-
139
- .status-list span {
140
- color: var(--muted);
57
+ .status {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ gap: 8px;
61
+ color: var(--ok);
141
62
  font-size: 13px;
142
- letter-spacing: 0.02em;
143
63
  }
144
64
 
145
- .status-list .ok {
146
- color: var(--accent);
147
- font-weight: 500;
65
+ .dot {
66
+ width: 8px;
67
+ height: 8px;
68
+ border-radius: 50%;
69
+ background: currentColor;
148
70
  }
149
71
 
150
- .meta {
151
- border-top: 1px solid var(--divider);
152
- padding-top: 14px;
72
+ dl {
73
+ margin: 0;
153
74
  display: grid;
154
- gap: 10px;
155
- }
156
-
157
- .meta-row {
158
- display: flex;
159
- justify-content: space-between;
160
- align-items: baseline;
75
+ grid-template-columns: 120px 1fr;
76
+ gap: 8px 12px;
161
77
  font-size: 13px;
162
- color: var(--muted);
163
- }
164
-
165
- .meta-row code {
166
- font-family: "Segoe UI", system-ui, -apple-system, "SFMono-Regular", Menlo, monospace;
167
- background: rgba(255, 255, 255, 0.04);
168
- border-radius: 8px;
169
- padding: 4px 8px;
170
- color: var(--text);
171
78
  }
172
79
 
173
- .tip {
174
- margin: 0;
175
- font-size: 13px;
80
+ dt {
176
81
  color: var(--muted);
177
- border-top: 1px solid var(--divider);
178
- padding-top: 14px;
179
82
  }
180
83
 
181
- .tip strong {
84
+ dd {
85
+ margin: 0;
182
86
  color: var(--text);
87
+ word-break: break-word;
183
88
  }
184
89
 
185
- footer {
90
+ code {
91
+ background: #171717;
92
+ border: 1px solid var(--line);
93
+ border-radius: 6px;
94
+ padding: 2px 6px;
95
+ font-family: inherit;
186
96
  font-size: 12px;
187
- color: var(--muted);
188
- text-align: center;
189
- }
190
-
191
- @keyframes fade {
192
- from { opacity: 0; transform: translateY(6px); }
193
- to { opacity: 1; transform: translateY(0); }
194
97
  }
195
98
 
196
- @media (prefers-reduced-motion: reduce) {
197
- .icon {
198
- animation: none;
199
- }
200
- }
201
-
202
- @media (max-width: 480px) {
203
- main {
204
- padding: 24px;
205
- border-radius: 18px;
206
- }
207
-
208
- .state {
209
- flex-direction: column;
210
- align-items: flex-start;
211
- gap: 4px;
212
- }
213
-
214
- .status-list li {
215
- flex-direction: column;
216
- align-items: flex-start;
217
- gap: 2px;
218
- }
219
-
220
- .meta-row {
221
- flex-direction: column;
222
- gap: 4px;
99
+ @media (max-width: 520px) {
100
+ dl {
101
+ grid-template-columns: 1fr;
223
102
  }
224
103
  }
225
104
  </style>
226
105
  </head>
227
106
  <body>
228
107
  <main role="main" aria-label="OAuth callback received">
229
- <p class="eyebrow">OpenAI Codex</p>
230
- <div class="icon" aria-hidden="true"></div>
231
- <h1>Callback received</h1>
232
- <p class="lead">Return to your terminal to complete sign-in.</p>
233
- <div class="state">
234
- <span>Status</span>
235
- <strong>Processing</strong>
108
+ <h1>Sign-in complete</h1>
109
+ <p>Return to your terminal to finish Codex login.</p>
110
+
111
+ <div class="status" aria-live="polite">
112
+ <span class="dot" aria-hidden="true"></span>
113
+ Callback received
236
114
  </div>
237
- <ul class="status-list" aria-label="OAuth steps">
238
- <li>
239
- <span>Authorization code</span>
240
- <span class="ok">received</span>
241
- </li>
242
- <li>
243
- <span>Token exchange</span>
244
- <span>running in terminal</span>
245
- </li>
246
- <li>
247
- <span>Credentials</span>
248
- <span>persisting after terminal completes</span>
249
- </li>
250
- <li>
251
- <span>Session</span>
252
- <span>activating in terminal</span>
253
- </li>
254
- </ul>
255
- <section class="meta" aria-label="Callback summary">
256
- <div class="meta-row">
257
- <span>Callback</span>
258
- <!-- Port 1455 is fixed by design via REDIRECT_URI -->
259
- <code>localhost:1455</code>
260
- </div>
261
- <div class="meta-row">
262
- <span>Tip</span>
263
- <span>Close this tab when you are done.</span>
264
- </div>
265
- </section>
266
- <p class="tip"><strong>Next:</strong> return to the terminal window to continue.</p>
267
- <footer>Back to terminal to continue.</footer>
115
+
116
+ <dl>
117
+ <dt>Endpoint</dt>
118
+ <dd><code>localhost:1455</code></dd>
119
+ <dt>Flow</dt>
120
+ <dd>OAuth callback captured</dd>
121
+ <dt>Next</dt>
122
+ <dd>Close this tab and continue in terminal</dd>
123
+ </dl>
268
124
  </main>
269
125
  </body>
270
- </html>
126
+ </html>
@@ -307,7 +307,7 @@ YOU ARE IN A DIFFERENT ENVIRONMENT. These instructions override ALL previous too
307
307
 
308
308
  <tool_replacements priority="0">
309
309
  <critical_rule priority="0">
310
- apply_patch/applyPatch are Codex names, but host tool names vary by version.
310
+ apply_patch/applyPatch are Codex names, but host tool names vary by version.
311
311
  - Inspect the actual tool list before editing.
312
312
  - If edit exists: use edit for precise in-place string replacements and hashline edits.
313
313
  - If edit is absent and apply_patch exists: use apply_patch for those precise/hashline edits in this plugin.
@@ -329,7 +329,7 @@ File Operations:
329
329
  - write - Create new files (if available)
330
330
  - edit - Modify existing files with string replacement (version-dependent)
331
331
  - oldString must be literal text from the current file; never pass unresolved placeholders like \${TARGET_SNIPPET}
332
- - apply_patch - May be the edit/patch tool name in newer host builds (version-dependent)
332
+ - apply_patch - May be the edit/patch tool name in newer host builds (version-dependent)
333
333
  - hashline_read - Read lines with hashline refs (L<line>#<hash>) for deterministic edits
334
334
  - patch - Apply diff patches (version-dependent)
335
335
  - read - Read file contents
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-paths.d.ts","sourceRoot":"","sources":["../../lib/runtime-paths.ts"],"names":[],"mappings":"AAkCA;;;;;;GAMG;AAEH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAwFD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAiC7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
1
+ {"version":3,"file":"runtime-paths.d.ts","sourceRoot":"","sources":["../../lib/runtime-paths.ts"],"names":[],"mappings":"AAkCA;;;;;;GAMG;AAEH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AA2GD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAiC7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -1,6 +1,6 @@
1
1
  import { homedir } from "node:os";
2
2
  import { join, win32 } from "node:path";
3
- import { existsSync } from "node:fs";
3
+ import { existsSync, readdirSync } from "node:fs";
4
4
  function firstNonEmpty(values) {
5
5
  for (const value of values) {
6
6
  const trimmed = (value ?? "").trim();
@@ -100,6 +100,28 @@ function hasAccountsStorage(dir) {
100
100
  if (existsSync(join(dir, fileName))) {
101
101
  return true;
102
102
  }
103
+ if (existsSync(join(dir, `${fileName}.wal`))) {
104
+ return true;
105
+ }
106
+ }
107
+ try {
108
+ const entries = readdirSync(dir, { withFileTypes: true });
109
+ for (const entry of entries) {
110
+ if (!entry.isFile())
111
+ continue;
112
+ for (const fileName of accountFiles) {
113
+ if (!entry.name.startsWith(`${fileName}.`))
114
+ continue;
115
+ if (entry.name.endsWith(".tmp"))
116
+ continue;
117
+ if (entry.name.includes(".rotate."))
118
+ continue;
119
+ return true;
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ // Ignore unreadable directories and fall back to known filename probes.
103
125
  }
104
126
  return false;
105
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-paths.js","sourceRoot":"","sources":["../../lib/runtime-paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-paths.js","sourceRoot":"","sources":["../../lib/runtime-paths.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../lib/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../lib/storage.ts"],"names":[],"mappings":"AAeA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;AAe3H,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,wBAAwB,EAAE,CAAC;CACrC;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAOrF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB3E;AAmFD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE9D;AA+ND,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CA2B/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAK9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAmLD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7H,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE,CAEL;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK/E;AAED,wBAAgB,0BAA0B,CAAC,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1G,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE,CAsDL;AA+BD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAyF9E;AAED;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAErE;AAqSD,wBAAsB,6BAA6B,CAAC,CAAC,EACnD,OAAO,EAAE,CACP,OAAO,EAAE,gBAAgB,GAAG,IAAI,EAChC,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,KAClD,OAAO,CAAC,CAAC,CAAC,GACd,OAAO,CAAC,CAAC,CAAC,CAKZ;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBnD;AA8ED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,uBAAuB,CAAC,CA+C5E;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBzF;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAW1D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyDpH"}
@@ -1,5 +1,5 @@
1
1
  import { promises as fs, existsSync } from "node:fs";
2
- import { dirname, join } from "node:path";
2
+ import { basename, dirname, join } from "node:path";
3
3
  import { createHash } from "node:crypto";
4
4
  import { ACCOUNT_LIMITS } from "./constants.js";
5
5
  import { createLogger } from "./logger.js";
@@ -67,6 +67,28 @@ function withStorageLock(fn) {
67
67
  });
68
68
  return previousMutex.then(fn).finally(() => releaseLock());
69
69
  }
70
+ function looksLikeSyntheticFixtureAccount(account) {
71
+ const email = typeof account.email === "string" ? account.email.trim().toLowerCase() : "";
72
+ const refreshToken = typeof account.refreshToken === "string" ? account.refreshToken.trim().toLowerCase() : "";
73
+ const accountId = typeof account.accountId === "string" ? account.accountId.trim().toLowerCase() : "";
74
+ if (!/^account\d+@example\.com$/.test(email)) {
75
+ return false;
76
+ }
77
+ const hasSyntheticRefreshToken = refreshToken.startsWith("fake_refresh") ||
78
+ /^fake_refresh_token_\d+(_for_testing_only)?$/.test(refreshToken);
79
+ if (!hasSyntheticRefreshToken) {
80
+ return false;
81
+ }
82
+ if (accountId.length === 0) {
83
+ return true;
84
+ }
85
+ return /^acc(_|-)?\d+$/.test(accountId);
86
+ }
87
+ function looksLikeSyntheticFixtureStorage(storage) {
88
+ if (!storage || storage.accounts.length === 0)
89
+ return false;
90
+ return storage.accounts.every((account) => looksLikeSyntheticFixtureAccount(account));
91
+ }
70
92
  async function ensureGitignore(storagePath) {
71
93
  if (!currentStoragePath)
72
94
  return;
@@ -117,6 +139,43 @@ function getAccountsBackupRecoveryCandidates(path) {
117
139
  }
118
140
  return candidates;
119
141
  }
142
+ async function getAccountsBackupRecoveryCandidatesWithDiscovery(path) {
143
+ const knownCandidates = getAccountsBackupRecoveryCandidates(path);
144
+ const discoveredCandidates = new Set();
145
+ const candidatePrefix = `${basename(path)}.`;
146
+ const knownCandidateSet = new Set(knownCandidates);
147
+ const directoryPath = dirname(path);
148
+ try {
149
+ const entries = await fs.readdir(directoryPath, { withFileTypes: true });
150
+ for (const entry of entries) {
151
+ if (!entry.isFile())
152
+ continue;
153
+ if (!entry.name.startsWith(candidatePrefix))
154
+ continue;
155
+ if (entry.name.endsWith(".tmp"))
156
+ continue;
157
+ if (entry.name.includes(".rotate."))
158
+ continue;
159
+ if (entry.name.endsWith(ACCOUNTS_WAL_SUFFIX))
160
+ continue;
161
+ const candidatePath = join(directoryPath, entry.name);
162
+ if (knownCandidateSet.has(candidatePath))
163
+ continue;
164
+ discoveredCandidates.add(candidatePath);
165
+ }
166
+ }
167
+ catch (error) {
168
+ const code = error.code;
169
+ if (code !== "ENOENT") {
170
+ log.warn("Failed to discover account backup candidates", {
171
+ path,
172
+ error: String(error),
173
+ });
174
+ }
175
+ }
176
+ const discoveredOrdered = Array.from(discoveredCandidates).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
177
+ return [...knownCandidates, ...discoveredOrdered];
178
+ }
120
179
  function getAccountsWalPath(path) {
121
180
  return `${path}${ACCOUNTS_WAL_SUFFIX}`;
122
181
  }
@@ -690,6 +749,50 @@ async function loadAccountsInternal(persistMigration) {
690
749
  }
691
750
  }
692
751
  }
752
+ const primaryLooksSynthetic = looksLikeSyntheticFixtureStorage(normalized);
753
+ if (storageBackupEnabled && normalized && primaryLooksSynthetic) {
754
+ const backupCandidates = await getAccountsBackupRecoveryCandidatesWithDiscovery(path);
755
+ for (const backupPath of backupCandidates) {
756
+ if (backupPath === path)
757
+ continue;
758
+ try {
759
+ const backup = await loadAccountsFromPath(backupPath);
760
+ if (!backup.normalized)
761
+ continue;
762
+ if (looksLikeSyntheticFixtureStorage(backup.normalized))
763
+ continue;
764
+ if (backup.normalized.accounts.length <= 0)
765
+ continue;
766
+ log.warn("Detected synthetic primary account storage; promoting backup", {
767
+ path,
768
+ backupPath,
769
+ primaryAccounts: normalized.accounts.length,
770
+ backupAccounts: backup.normalized.accounts.length,
771
+ });
772
+ if (persistMigration) {
773
+ try {
774
+ await persistMigration(backup.normalized);
775
+ }
776
+ catch (persistError) {
777
+ log.warn("Failed to persist promoted backup storage", {
778
+ path,
779
+ error: String(persistError),
780
+ });
781
+ }
782
+ }
783
+ return backup.normalized;
784
+ }
785
+ catch (backupError) {
786
+ const backupCode = backupError.code;
787
+ if (backupCode !== "ENOENT") {
788
+ log.warn("Failed to load candidate backup for synthetic-primary promotion", {
789
+ path: backupPath,
790
+ error: String(backupError),
791
+ });
792
+ }
793
+ }
794
+ }
795
+ }
693
796
  return normalized;
694
797
  }
695
798
  catch (error) {
@@ -713,7 +816,7 @@ async function loadAccountsInternal(persistMigration) {
713
816
  return recoveredFromWal;
714
817
  }
715
818
  if (storageBackupEnabled) {
716
- const backupCandidates = getAccountsBackupRecoveryCandidates(path);
819
+ const backupCandidates = await getAccountsBackupRecoveryCandidatesWithDiscovery(path);
717
820
  for (const backupPath of backupCandidates) {
718
821
  try {
719
822
  const backup = await loadAccountsFromPath(backupPath);
@@ -764,6 +867,20 @@ async function saveAccountsUnlocked(storage) {
764
867
  try {
765
868
  await fs.mkdir(dirname(path), { recursive: true });
766
869
  await ensureGitignore(path);
870
+ if (looksLikeSyntheticFixtureStorage(storage)) {
871
+ try {
872
+ const existing = await loadNormalizedStorageFromPath(path, "existing account storage");
873
+ if (existing && existing.accounts.length > 0 && !looksLikeSyntheticFixtureStorage(existing)) {
874
+ throw new StorageError("Refusing to overwrite non-synthetic account storage with synthetic fixture payload", "EINVALID", path, "Detected synthetic fixture-like account payload. Use explicit account import/login commands instead.");
875
+ }
876
+ }
877
+ catch (error) {
878
+ if (error instanceof StorageError) {
879
+ throw error;
880
+ }
881
+ // Ignore existing-file probe failures and continue with normal save flow.
882
+ }
883
+ }
767
884
  if (storageBackupEnabled && existsSync(path)) {
768
885
  try {
769
886
  await createRotatingAccountsBackup(path);