@cortexkit/antigravity-auth-core 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-manager.d.ts +281 -0
- package/dist/account-manager.d.ts.map +1 -0
- package/dist/account-manager.js +1378 -0
- package/dist/account-manager.js.map +1 -0
- package/dist/account-storage.d.ts +162 -0
- package/dist/account-storage.d.ts.map +1 -0
- package/dist/account-storage.js +635 -0
- package/dist/account-storage.js.map +1 -0
- package/dist/account-types.d.ts +136 -0
- package/dist/account-types.d.ts.map +1 -0
- package/dist/account-types.js +9 -0
- package/dist/account-types.js.map +1 -0
- package/dist/agy-request-metadata.d.ts +12 -5
- package/dist/agy-request-metadata.d.ts.map +1 -1
- package/dist/agy-request-metadata.js +64 -38
- package/dist/agy-request-metadata.js.map +1 -1
- package/dist/agy-transport.d.ts +2 -2
- package/dist/agy-transport.d.ts.map +1 -1
- package/dist/agy-transport.js +87 -74
- package/dist/agy-transport.js.map +1 -1
- package/dist/antigravity/oauth.d.ts +3 -2
- package/dist/antigravity/oauth.d.ts.map +1 -1
- package/dist/antigravity/oauth.js +65 -55
- package/dist/antigravity/oauth.js.map +1 -1
- package/dist/atomic-write.d.ts +23 -0
- package/dist/atomic-write.d.ts.map +1 -0
- package/dist/atomic-write.js +47 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/auth-types.d.ts +2 -2
- package/dist/auth-types.d.ts.map +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +9 -6
- package/dist/auth.js.map +1 -1
- package/dist/constants.d.ts +19 -12
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +51 -39
- package/dist/constants.js.map +1 -1
- package/dist/fetch-timeout.d.ts +26 -0
- package/dist/fetch-timeout.d.ts.map +1 -0
- package/dist/fetch-timeout.js +43 -0
- package/dist/fetch-timeout.js.map +1 -0
- package/dist/file-lock.d.ts +79 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +438 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/fingerprint.d.ts +9 -3
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +28 -20
- package/dist/fingerprint.js.map +1 -1
- package/dist/index.d.ts +23 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -9
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +10 -10
- package/dist/logger.js.map +1 -1
- package/dist/model-registry.d.ts +5 -5
- package/dist/model-registry.d.ts.map +1 -1
- package/dist/model-registry.js +107 -106
- package/dist/model-registry.js.map +1 -1
- package/dist/project.d.ts +1 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +53 -25
- package/dist/project.js.map +1 -1
- package/dist/quota-manager.d.ts +140 -0
- package/dist/quota-manager.d.ts.map +1 -0
- package/dist/quota-manager.js +481 -0
- package/dist/quota-manager.js.map +1 -0
- package/dist/quota-types.d.ts +49 -0
- package/dist/quota-types.d.ts.map +1 -0
- package/dist/quota-types.js +10 -0
- package/dist/quota-types.js.map +1 -0
- package/dist/rotation.d.ts +175 -0
- package/dist/rotation.d.ts.map +1 -0
- package/dist/rotation.js +391 -0
- package/dist/rotation.js.map +1 -0
- package/dist/transform/claude.d.ts +1 -1
- package/dist/transform/claude.d.ts.map +1 -1
- package/dist/transform/claude.js +63 -41
- package/dist/transform/claude.js.map +1 -1
- package/dist/transform/cross-model-sanitizer.d.ts +1 -1
- package/dist/transform/cross-model-sanitizer.d.ts.map +1 -1
- package/dist/transform/cross-model-sanitizer.js +19 -16
- package/dist/transform/cross-model-sanitizer.js.map +1 -1
- package/dist/transform/gemini.d.ts +1 -1
- package/dist/transform/gemini.d.ts.map +1 -1
- package/dist/transform/gemini.js +111 -85
- package/dist/transform/gemini.js.map +1 -1
- package/dist/transform/index.d.ts +9 -9
- package/dist/transform/index.d.ts.map +1 -1
- package/dist/transform/index.js +6 -6
- package/dist/transform/index.js.map +1 -1
- package/dist/transform/model-resolver.d.ts +5 -5
- package/dist/transform/model-resolver.d.ts.map +1 -1
- package/dist/transform/model-resolver.js +97 -75
- package/dist/transform/model-resolver.js.map +1 -1
- package/dist/transform/types.d.ts +5 -5
- package/dist/transform/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +14 -16
- package/dist/version.js.map +1 -1
- package/package.json +16 -10
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock-held account storage engine.
|
|
3
|
+
*
|
|
4
|
+
* Owns the on-disk schema for the multi-account pool (v4) plus every
|
|
5
|
+
* migration from older versions, the load/merge/save primitives, and a
|
|
6
|
+
* `mutateAccountStorage` entry point that holds a fenced file lock for
|
|
7
|
+
* the duration of read-modify-write. Concurrent writes retry up to a
|
|
8
|
+
* bounded schedule (`100, 200, 400, 800, 1000ms` with factor 2 / max 1000)
|
|
9
|
+
* before surfacing a typed `AccountStorageLockContentionError`.
|
|
10
|
+
*
|
|
11
|
+
* Fail-closed semantics: when the accounts file exists but cannot be
|
|
12
|
+
* read as a valid v4 (parse error, schema mismatch, unknown future
|
|
13
|
+
* version, I/O error), `mutateAccountStorage` and `loadAccountStorage`
|
|
14
|
+
* throw a typed `AccountStorageUnreadableError` instead of treating
|
|
15
|
+
* the bad state as "empty pool" and overwriting the file on the next
|
|
16
|
+
* write. A best-effort `.corrupt-<ISO-timestamp>` backup is created
|
|
17
|
+
* before throwing so a future bug can never permanently destroy user
|
|
18
|
+
* data. The backup itself never throws.
|
|
19
|
+
*
|
|
20
|
+
* This module is harness-agnostic: it does not own a path (the harness
|
|
21
|
+
* adapter passes one in via `loadAccountStorage(path)`). The harness is
|
|
22
|
+
* responsible for picking the right on-disk path and ensuring the parent
|
|
23
|
+
* directory exists.
|
|
24
|
+
*/
|
|
25
|
+
import { chmod, copyFile, mkdir, readFile, unlink } from 'node:fs/promises';
|
|
26
|
+
import { dirname } from 'node:path';
|
|
27
|
+
import { writeJsonAtomic } from "./atomic-write.js";
|
|
28
|
+
import { acquireFencedFileLock } from "./file-lock.js";
|
|
29
|
+
import { createLogger } from "./logger.js";
|
|
30
|
+
const log = createLogger('account-storage');
|
|
31
|
+
/**
|
|
32
|
+
* Thrown when `mutateAccountStorage` exhausts its initial attempt plus
|
|
33
|
+
* five retries against a lock that is still held. Surfaces a typed
|
|
34
|
+
* signal harnesses can distinguish from transient I/O errors.
|
|
35
|
+
*/
|
|
36
|
+
export class AccountStorageLockContentionError extends Error {
|
|
37
|
+
details;
|
|
38
|
+
constructor(message, details) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'AccountStorageLockContentionError';
|
|
41
|
+
this.details = details;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Thrown when the on-disk accounts file exists but cannot be read as
|
|
46
|
+
* a valid v4. Distinguishes ENOENT (first-run UX: missing file is
|
|
47
|
+
* fine) from "the file is there but we can't trust it" (fail closed).
|
|
48
|
+
*
|
|
49
|
+
* `backupPath` is set when a `.corrupt-<ISO-timestamp>` sidecar was
|
|
50
|
+
* successfully written; consumers should mention it in any user-facing
|
|
51
|
+
* recovery message so the user knows their data is preserved.
|
|
52
|
+
*/
|
|
53
|
+
export class AccountStorageUnreadableError extends Error {
|
|
54
|
+
details;
|
|
55
|
+
constructor(message, details) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = 'AccountStorageUnreadableError';
|
|
58
|
+
this.details = details;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Configuration for the lock-acquisition retry schedule. Mirrors the
|
|
63
|
+
* legacy wait-and-retry schedule (5 retries, 100ms min, 1000ms max,
|
|
64
|
+
* factor 2) so an immediate contention throw is a regression.
|
|
65
|
+
*/
|
|
66
|
+
const RETRY_DELAYS_MS = [100, 200, 400, 800, 1000];
|
|
67
|
+
const DEFAULT_SLEEP = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
68
|
+
const DEFAULT_BUILD_BACKUP_PATH = (path, now) => `${path}.corrupt-${now.toISOString().replace(/[:.]/g, '-')}`;
|
|
69
|
+
async function ensureSecurePermissions(path) {
|
|
70
|
+
try {
|
|
71
|
+
await chmod(path, 0o600);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// best-effort; Windows + non-POSIX FS ignore this.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function _ensureFileExists(path) {
|
|
78
|
+
try {
|
|
79
|
+
await readFile(path);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
await mkdir(dirname(path), { recursive: true });
|
|
83
|
+
await writeJsonAtomic(path, { version: 4, accounts: [], activeIndex: 0 });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Copy a corrupt file to a `.corrupt-<ISO-timestamp>` sidecar. The
|
|
88
|
+
* backup itself never throws — if it fails (e.g. disk full, permission
|
|
89
|
+
* denied on the sidecar path), the original unreadable error is what
|
|
90
|
+
* the caller sees. Returns the backup path on success, `null` on
|
|
91
|
+
* failure.
|
|
92
|
+
*/
|
|
93
|
+
async function backupCorruptFile(sourcePath, buildBackupPath, now) {
|
|
94
|
+
const backupPath = buildBackupPath(sourcePath, now);
|
|
95
|
+
if (!backupPath)
|
|
96
|
+
return null;
|
|
97
|
+
try {
|
|
98
|
+
await copyFile(sourcePath, backupPath);
|
|
99
|
+
await ensureSecurePermissions(backupPath);
|
|
100
|
+
return backupPath;
|
|
101
|
+
}
|
|
102
|
+
catch (backupError) {
|
|
103
|
+
log.warn('Failed to back up corrupt account storage file', {
|
|
104
|
+
sourcePath,
|
|
105
|
+
backupPath,
|
|
106
|
+
error: String(backupError),
|
|
107
|
+
});
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Deduplicate accounts that share an email, keeping the entry with the
|
|
113
|
+
* newest `lastUsed` then `addedAt`. Order of the kept entries in the
|
|
114
|
+
* output array is determined by the position of the *newest* matching
|
|
115
|
+
* account in the input array (not necessarily the original positions).
|
|
116
|
+
*/
|
|
117
|
+
export function deduplicateAccountsByEmail(accounts) {
|
|
118
|
+
const emailToNewestIndex = new Map();
|
|
119
|
+
const indicesToKeep = new Set();
|
|
120
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
121
|
+
const acc = accounts[i];
|
|
122
|
+
if (!acc)
|
|
123
|
+
continue;
|
|
124
|
+
if (!acc.email) {
|
|
125
|
+
indicesToKeep.add(i);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const existingIndex = emailToNewestIndex.get(acc.email);
|
|
129
|
+
if (existingIndex === undefined) {
|
|
130
|
+
emailToNewestIndex.set(acc.email, i);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const existing = accounts[existingIndex];
|
|
134
|
+
if (!existing) {
|
|
135
|
+
emailToNewestIndex.set(acc.email, i);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const currLastUsed = acc.lastUsed || 0;
|
|
139
|
+
const existLastUsed = existing.lastUsed || 0;
|
|
140
|
+
const currAddedAt = acc.addedAt || 0;
|
|
141
|
+
const existAddedAt = existing.addedAt || 0;
|
|
142
|
+
const isNewer = currLastUsed > existLastUsed ||
|
|
143
|
+
(currLastUsed === existLastUsed && currAddedAt > existAddedAt);
|
|
144
|
+
if (isNewer) {
|
|
145
|
+
emailToNewestIndex.set(acc.email, i);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (const idx of emailToNewestIndex.values()) {
|
|
149
|
+
indicesToKeep.add(idx);
|
|
150
|
+
}
|
|
151
|
+
const result = [];
|
|
152
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
153
|
+
if (indicesToKeep.has(i)) {
|
|
154
|
+
const acc = accounts[i];
|
|
155
|
+
if (acc) {
|
|
156
|
+
result.push(acc);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
function migrateV1ToV2(v1) {
|
|
163
|
+
return {
|
|
164
|
+
version: 2,
|
|
165
|
+
accounts: v1.accounts.map((acc) => {
|
|
166
|
+
const rateLimitResetTimes = {};
|
|
167
|
+
if (acc.isRateLimited &&
|
|
168
|
+
acc.rateLimitResetTime &&
|
|
169
|
+
acc.rateLimitResetTime > Date.now()) {
|
|
170
|
+
rateLimitResetTimes.claude = acc.rateLimitResetTime;
|
|
171
|
+
rateLimitResetTimes.gemini = acc.rateLimitResetTime;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
email: acc.email,
|
|
175
|
+
refreshToken: acc.refreshToken,
|
|
176
|
+
projectId: acc.projectId,
|
|
177
|
+
managedProjectId: acc.managedProjectId,
|
|
178
|
+
addedAt: acc.addedAt,
|
|
179
|
+
lastUsed: acc.lastUsed,
|
|
180
|
+
lastSwitchReason: acc.lastSwitchReason,
|
|
181
|
+
rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0
|
|
182
|
+
? rateLimitResetTimes
|
|
183
|
+
: undefined,
|
|
184
|
+
};
|
|
185
|
+
}),
|
|
186
|
+
activeIndex: v1.activeIndex,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
export function migrateV2ToV3(v2) {
|
|
190
|
+
return {
|
|
191
|
+
version: 3,
|
|
192
|
+
accounts: v2.accounts.map((acc) => {
|
|
193
|
+
const rateLimitResetTimes = {};
|
|
194
|
+
if (acc.rateLimitResetTimes?.claude &&
|
|
195
|
+
acc.rateLimitResetTimes.claude > Date.now()) {
|
|
196
|
+
rateLimitResetTimes.claude = acc.rateLimitResetTimes.claude;
|
|
197
|
+
}
|
|
198
|
+
if (acc.rateLimitResetTimes?.gemini &&
|
|
199
|
+
acc.rateLimitResetTimes.gemini > Date.now()) {
|
|
200
|
+
rateLimitResetTimes['gemini-antigravity'] =
|
|
201
|
+
acc.rateLimitResetTimes.gemini;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
email: acc.email,
|
|
205
|
+
refreshToken: acc.refreshToken,
|
|
206
|
+
projectId: acc.projectId,
|
|
207
|
+
managedProjectId: acc.managedProjectId,
|
|
208
|
+
addedAt: acc.addedAt,
|
|
209
|
+
lastUsed: acc.lastUsed,
|
|
210
|
+
lastSwitchReason: acc.lastSwitchReason,
|
|
211
|
+
rateLimitResetTimes: Object.keys(rateLimitResetTimes).length > 0
|
|
212
|
+
? rateLimitResetTimes
|
|
213
|
+
: undefined,
|
|
214
|
+
};
|
|
215
|
+
}),
|
|
216
|
+
activeIndex: v2.activeIndex,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function migrateV3ToV4(v3) {
|
|
220
|
+
return {
|
|
221
|
+
version: 4,
|
|
222
|
+
accounts: v3.accounts.map((acc) => ({
|
|
223
|
+
...acc,
|
|
224
|
+
fingerprint: undefined,
|
|
225
|
+
fingerprintHistory: undefined,
|
|
226
|
+
})),
|
|
227
|
+
activeIndex: v3.activeIndex,
|
|
228
|
+
activeIndexByFamily: v3.activeIndexByFamily,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Merge two v4 account pools keyed by `refreshToken`. Preserves
|
|
233
|
+
* `projectId`/`managedProjectId` from either side when the incoming
|
|
234
|
+
* payload omits them. Eligibility state survives via a per-field
|
|
235
|
+
* `eligibilityStateUpdatedAt` comparison so a stale concurrent writer
|
|
236
|
+
* cannot regress an explicit ineligible decision.
|
|
237
|
+
*/
|
|
238
|
+
export function mergeAccountStorage(existing, incoming) {
|
|
239
|
+
const accountMap = new Map();
|
|
240
|
+
for (const acc of existing.accounts) {
|
|
241
|
+
if (acc.refreshToken) {
|
|
242
|
+
accountMap.set(acc.refreshToken, acc);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
for (const acc of incoming.accounts) {
|
|
246
|
+
if (!acc.refreshToken)
|
|
247
|
+
continue;
|
|
248
|
+
const existingAcc = accountMap.get(acc.refreshToken);
|
|
249
|
+
if (existingAcc) {
|
|
250
|
+
const eligibilitySource = (acc.eligibilityStateUpdatedAt ?? 0) >=
|
|
251
|
+
(existingAcc.eligibilityStateUpdatedAt ?? 0)
|
|
252
|
+
? acc
|
|
253
|
+
: existingAcc;
|
|
254
|
+
const merged = {
|
|
255
|
+
...existingAcc,
|
|
256
|
+
...acc,
|
|
257
|
+
projectId: acc.projectId ?? existingAcc.projectId,
|
|
258
|
+
managedProjectId: acc.managedProjectId ?? existingAcc.managedProjectId,
|
|
259
|
+
rateLimitResetTimes: {
|
|
260
|
+
...existingAcc.rateLimitResetTimes,
|
|
261
|
+
...acc.rateLimitResetTimes,
|
|
262
|
+
},
|
|
263
|
+
lastUsed: Math.max(existingAcc.lastUsed || 0, acc.lastUsed || 0),
|
|
264
|
+
accountIneligible: eligibilitySource.accountIneligible,
|
|
265
|
+
accountIneligibleAt: eligibilitySource.accountIneligibleAt,
|
|
266
|
+
accountIneligibleReason: eligibilitySource.accountIneligibleReason,
|
|
267
|
+
eligibilityStateUpdatedAt: eligibilitySource.eligibilityStateUpdatedAt,
|
|
268
|
+
};
|
|
269
|
+
if (merged.accountIneligible) {
|
|
270
|
+
merged.enabled = false;
|
|
271
|
+
}
|
|
272
|
+
accountMap.set(acc.refreshToken, merged);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
accountMap.set(acc.refreshToken, acc);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
version: 4,
|
|
280
|
+
accounts: Array.from(accountMap.values()),
|
|
281
|
+
activeIndex: incoming.activeIndex,
|
|
282
|
+
activeIndexByFamily: incoming.activeIndexByFamily,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Read the on-disk file and reduce it to a `StorageReadOutcome`. Used
|
|
287
|
+
* by `mutateAccountStorage` (which needs to distinguish "missing →
|
|
288
|
+
* first-run empty pool" from "exists but unreadable → refuse to write")
|
|
289
|
+
* and by `loadAccountStorage` (which maps unreadable to a thrown error).
|
|
290
|
+
*/
|
|
291
|
+
async function readAndNormalizeV4(path) {
|
|
292
|
+
let raw;
|
|
293
|
+
try {
|
|
294
|
+
raw = await readFile(path, 'utf-8');
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
const code = error.code;
|
|
298
|
+
if (code === 'ENOENT') {
|
|
299
|
+
return { state: 'missing' };
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
state: 'unreadable',
|
|
303
|
+
reason: 'io-error',
|
|
304
|
+
detail: `${code ?? 'UNKNOWN'}: ${error.message ?? String(error)}`,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
let parsed;
|
|
308
|
+
try {
|
|
309
|
+
parsed = JSON.parse(raw);
|
|
310
|
+
}
|
|
311
|
+
catch (parseError) {
|
|
312
|
+
return {
|
|
313
|
+
state: 'unreadable',
|
|
314
|
+
reason: 'malformed-json',
|
|
315
|
+
detail: parseError.message ?? String(parseError),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
319
|
+
return {
|
|
320
|
+
state: 'unreadable',
|
|
321
|
+
reason: 'invalid-shape',
|
|
322
|
+
detail: 'top-level value is not an object',
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
const candidate = parsed;
|
|
326
|
+
if (!Array.isArray(candidate.accounts)) {
|
|
327
|
+
return {
|
|
328
|
+
state: 'unreadable',
|
|
329
|
+
reason: 'invalid-shape',
|
|
330
|
+
detail: '`accounts` is missing or not an array',
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
const parsedVersion = candidate.version;
|
|
334
|
+
if (parsedVersion !== 1 &&
|
|
335
|
+
parsedVersion !== 2 &&
|
|
336
|
+
parsedVersion !== 3 &&
|
|
337
|
+
parsedVersion !== 4) {
|
|
338
|
+
return {
|
|
339
|
+
state: 'unreadable',
|
|
340
|
+
reason: 'unsupported-version',
|
|
341
|
+
detail: `unsupported version: ${String(parsedVersion)}`,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
let storage = null;
|
|
345
|
+
switch (parsedVersion) {
|
|
346
|
+
case 1:
|
|
347
|
+
storage = migrateV3ToV4(migrateV2ToV3(migrateV1ToV2(parsed)));
|
|
348
|
+
break;
|
|
349
|
+
case 2:
|
|
350
|
+
storage = migrateV3ToV4(migrateV2ToV3(parsed));
|
|
351
|
+
break;
|
|
352
|
+
case 3:
|
|
353
|
+
storage = migrateV3ToV4(parsed);
|
|
354
|
+
break;
|
|
355
|
+
case 4:
|
|
356
|
+
storage = parsed;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
if (!storage) {
|
|
360
|
+
return {
|
|
361
|
+
state: 'unreadable',
|
|
362
|
+
reason: 'unsupported-version',
|
|
363
|
+
detail: `unhandled version after switch: ${String(parsedVersion)}`,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
// Strict per-record validation. A v4 record must be a non-null object
|
|
367
|
+
// with a string `refreshToken`, finite numeric `addedAt` and `lastUsed`.
|
|
368
|
+
// Legacy versions (v1/v2/v3) reach this point only after migration,
|
|
369
|
+
// which already threw on a non-object entry and produced a populated
|
|
370
|
+
// refreshToken by reading it directly — so a record that survived
|
|
371
|
+
// migration is fine. We do NOT validate legacy versions BEFORE
|
|
372
|
+
// migration because the migration itself enforces the required fields
|
|
373
|
+
// by reading them off the input shape.
|
|
374
|
+
for (let i = 0; i < storage.accounts.length; i++) {
|
|
375
|
+
const detail = validateV4AccountRecord(storage.accounts[i], i);
|
|
376
|
+
if (detail !== null) {
|
|
377
|
+
return {
|
|
378
|
+
state: 'unreadable',
|
|
379
|
+
reason: 'invalid-shape',
|
|
380
|
+
detail,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const deduplicatedAccounts = deduplicateAccountsByEmail(storage.accounts);
|
|
385
|
+
let activeIndex = typeof storage.activeIndex === 'number' &&
|
|
386
|
+
Number.isFinite(storage.activeIndex)
|
|
387
|
+
? storage.activeIndex
|
|
388
|
+
: 0;
|
|
389
|
+
if (deduplicatedAccounts.length > 0) {
|
|
390
|
+
activeIndex = Math.min(activeIndex, deduplicatedAccounts.length - 1);
|
|
391
|
+
activeIndex = Math.max(activeIndex, 0);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
activeIndex = 0;
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
state: 'ok',
|
|
398
|
+
storage: {
|
|
399
|
+
version: 4,
|
|
400
|
+
accounts: deduplicatedAccounts,
|
|
401
|
+
activeIndex,
|
|
402
|
+
activeIndexByFamily: storage.activeIndexByFamily,
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Return a human-readable detail string when `record` is not a valid
|
|
408
|
+
* v4 account record, `null` when it is. Used by `readAndNormalizeV4`
|
|
409
|
+
* to surface per-record shape problems as `invalid-shape`
|
|
410
|
+
* `AccountStorageUnreadableError` instances instead of silently
|
|
411
|
+
* filtering them out — the latter used to drop a malformed account
|
|
412
|
+
* without any user-visible signal and risked losing data.
|
|
413
|
+
*/
|
|
414
|
+
function validateV4AccountRecord(record, index) {
|
|
415
|
+
if (record === null || typeof record !== 'object' || Array.isArray(record)) {
|
|
416
|
+
return `accounts[${index}] is not an object`;
|
|
417
|
+
}
|
|
418
|
+
const acc = record;
|
|
419
|
+
if (typeof acc.refreshToken !== 'string' || acc.refreshToken.length === 0) {
|
|
420
|
+
return `accounts[${index}].refreshToken is missing or not a non-empty string`;
|
|
421
|
+
}
|
|
422
|
+
if (typeof acc.addedAt !== 'number' || !Number.isFinite(acc.addedAt)) {
|
|
423
|
+
return `accounts[${index}].addedAt is missing or not a finite number`;
|
|
424
|
+
}
|
|
425
|
+
if (typeof acc.lastUsed !== 'number' || !Number.isFinite(acc.lastUsed)) {
|
|
426
|
+
return `accounts[${index}].lastUsed is missing or not a finite number`;
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Load the account pool from `path`, migrating older versions in-place
|
|
432
|
+
* to v4 and persisting the migrated copy.
|
|
433
|
+
*
|
|
434
|
+
* Returns `null` when the file does not exist (first-run UX).
|
|
435
|
+
*
|
|
436
|
+
* Throws `AccountStorageUnreadableError` when the file exists but
|
|
437
|
+
* cannot be read as a valid v4 — callers must NOT treat this as an
|
|
438
|
+
* empty pool, or they will silently destroy the user's data on the
|
|
439
|
+
* next write.
|
|
440
|
+
*/
|
|
441
|
+
export async function loadAccountStorage(path) {
|
|
442
|
+
const buildBackupPath = DEFAULT_BUILD_BACKUP_PATH;
|
|
443
|
+
const now = () => new Date();
|
|
444
|
+
await ensureSecurePermissions(path);
|
|
445
|
+
const outcome = await readAndNormalizeV4(path);
|
|
446
|
+
if (outcome.state === 'missing') {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
if (outcome.state === 'unreadable') {
|
|
450
|
+
const backupPath = await backupCorruptFile(path, buildBackupPath, now());
|
|
451
|
+
throw new AccountStorageUnreadableError(`Account storage at ${path} is unreadable (${outcome.reason}: ${outcome.detail}).` +
|
|
452
|
+
(backupPath
|
|
453
|
+
? ` A backup was written to ${backupPath}. The plugin will refuse to write until the file is removed or repaired.`
|
|
454
|
+
: ' A backup could not be written; the file has been left in place. The plugin will refuse to write until the file is removed or repaired.'), {
|
|
455
|
+
path,
|
|
456
|
+
reason: outcome.reason,
|
|
457
|
+
detail: outcome.detail,
|
|
458
|
+
backupPath,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
// Persist the migrated copy for v1/v2/v3 so subsequent loads are
|
|
462
|
+
// a single pass. Migration never changes semantics; a write failure
|
|
463
|
+
// is logged but not fatal — the in-memory result is still correct.
|
|
464
|
+
if (outcome.storage.version === 4) {
|
|
465
|
+
const onDiskVersion = await readVersionOnly(path);
|
|
466
|
+
if (onDiskVersion !== null && onDiskVersion !== 4) {
|
|
467
|
+
try {
|
|
468
|
+
await saveAccountStorage(path, outcome.storage);
|
|
469
|
+
log.info('Migration to v4 complete');
|
|
470
|
+
}
|
|
471
|
+
catch (saveError) {
|
|
472
|
+
log.warn('Failed to persist migrated storage', {
|
|
473
|
+
error: String(saveError),
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return outcome.storage;
|
|
479
|
+
}
|
|
480
|
+
async function readVersionOnly(path) {
|
|
481
|
+
try {
|
|
482
|
+
const raw = await readFile(path, 'utf-8');
|
|
483
|
+
const parsed = JSON.parse(raw);
|
|
484
|
+
return typeof parsed.version === 'number' ? parsed.version : null;
|
|
485
|
+
}
|
|
486
|
+
catch {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Acquire the lock for `path`, retrying on contention up to the legacy
|
|
492
|
+
* wait-and-retry schedule (`100, 200, 400, 800, 1000ms`) so an
|
|
493
|
+
* immediate contention throw is a regression. Throws a typed
|
|
494
|
+
* `AccountStorageLockContentionError` after the initial attempt plus
|
|
495
|
+
* five retries — but only when the failure mode is "another writer
|
|
496
|
+
* holds the lock" (`null` from `acquireFencedFileLock`). Real I/O
|
|
497
|
+
* errors (permission denied, missing path, disk failure) are rethrown
|
|
498
|
+
* immediately so callers can distinguish them from contention.
|
|
499
|
+
*/
|
|
500
|
+
async function acquireWithRetry(path, sleep) {
|
|
501
|
+
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
|
|
502
|
+
// acquireFencedFileLock throws on real I/O failure (permission,
|
|
503
|
+
// missing dir, disk error); it only returns `null` for a live,
|
|
504
|
+
// contended lock. Rethrow immediately so callers don't mistake a
|
|
505
|
+
// missing config dir for "someone else is writing".
|
|
506
|
+
const lock = await acquireFencedFileLock({
|
|
507
|
+
path,
|
|
508
|
+
name: 'accounts',
|
|
509
|
+
ttlMs: 10_000,
|
|
510
|
+
renew: true,
|
|
511
|
+
});
|
|
512
|
+
if (lock) {
|
|
513
|
+
return lock;
|
|
514
|
+
}
|
|
515
|
+
if (attempt < RETRY_DELAYS_MS.length) {
|
|
516
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
517
|
+
if (delay !== undefined) {
|
|
518
|
+
await sleep(delay);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
throw new AccountStorageLockContentionError(`account storage lock contention at ${path} after ${RETRY_DELAYS_MS.length + 1} attempts`, {
|
|
523
|
+
path,
|
|
524
|
+
attempts: RETRY_DELAYS_MS.length + 1,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Run `mutate` against the freshest persisted pool while holding the
|
|
529
|
+
* file lock. The mutator may return a partial v4 (or `undefined` to
|
|
530
|
+
* keep the input unchanged) and is guaranteed to see the post-migration
|
|
531
|
+
* v4 shape.
|
|
532
|
+
*
|
|
533
|
+
* Throws `AccountStorageLockContentionError` after exhausting the
|
|
534
|
+
* retry schedule against a lock that is still held by another writer.
|
|
535
|
+
*
|
|
536
|
+
* Throws `AccountStorageUnreadableError` when the file exists but
|
|
537
|
+
* cannot be read as a valid v4. In that case the file is first copied
|
|
538
|
+
* to a `.corrupt-<ISO-timestamp>` sidecar (best-effort) and the write
|
|
539
|
+
* is aborted — a user with a corrupt-but-recoverable accounts file (or
|
|
540
|
+
* one written by a newer plugin version) who adds one account MUST NOT
|
|
541
|
+
* have their entire pool silently destroyed.
|
|
542
|
+
*/
|
|
543
|
+
export async function mutateAccountStorage(path, mutate, options = {}) {
|
|
544
|
+
const sleep = options.sleep ?? DEFAULT_SLEEP;
|
|
545
|
+
const buildBackupPath = options.buildBackupPath ?? DEFAULT_BUILD_BACKUP_PATH;
|
|
546
|
+
const now = options.now ?? (() => new Date());
|
|
547
|
+
const lock = await acquireWithRetry(path, sleep);
|
|
548
|
+
try {
|
|
549
|
+
const outcome = await readAndNormalizeV4(path);
|
|
550
|
+
if (outcome.state === 'unreadable') {
|
|
551
|
+
const backupPath = await backupCorruptFile(path, buildBackupPath, now());
|
|
552
|
+
throw new AccountStorageUnreadableError(`Refusing to write: account storage at ${path} is unreadable (${outcome.reason}: ${outcome.detail}).` +
|
|
553
|
+
(backupPath
|
|
554
|
+
? ` A backup of the existing file was written to ${backupPath} and the on-disk file has been left untouched. Repair or remove the existing file before retrying.`
|
|
555
|
+
: ' A backup could not be written; the on-disk file has been left untouched. Repair or remove the existing file before retrying.'), {
|
|
556
|
+
path,
|
|
557
|
+
reason: outcome.reason,
|
|
558
|
+
detail: outcome.detail,
|
|
559
|
+
backupPath,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
const existing = outcome.state === 'ok'
|
|
563
|
+
? outcome.storage
|
|
564
|
+
: { version: 4, accounts: [], activeIndex: 0 };
|
|
565
|
+
// The mutator may be sync or async; awaiting its result lets long
|
|
566
|
+
// mutators hold the lock for the duration of their work (the OS-level
|
|
567
|
+
// create-lock + renewal keeps us exclusive that whole time).
|
|
568
|
+
const next = await mutate(existing);
|
|
569
|
+
const finalStorage = next ?? existing;
|
|
570
|
+
await lock.assertOwned();
|
|
571
|
+
await writeJsonAtomic(path, finalStorage);
|
|
572
|
+
return finalStorage;
|
|
573
|
+
}
|
|
574
|
+
finally {
|
|
575
|
+
try {
|
|
576
|
+
await lock.release();
|
|
577
|
+
}
|
|
578
|
+
catch (releaseError) {
|
|
579
|
+
log.warn('Failed to release account storage lock', {
|
|
580
|
+
error: String(releaseError),
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Merge `incoming` into the persisted pool under the lock. Returns the
|
|
587
|
+
* merged v4 result that was written to disk.
|
|
588
|
+
*/
|
|
589
|
+
export async function saveAccountStorage(path, incoming) {
|
|
590
|
+
return mutateAccountStorage(path, (current) => mergeAccountStorage(current, incoming));
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Write `incoming` to disk unconditionally (no merge). Required for
|
|
594
|
+
* destructive operations like delete where the next-state must replace
|
|
595
|
+
* — never be merged with — what is on disk.
|
|
596
|
+
*/
|
|
597
|
+
export async function saveAccountStorageReplace(path, incoming) {
|
|
598
|
+
return mutateAccountStorage(path, () => incoming);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Unlink the persisted pool while holding the lock so a concurrent
|
|
602
|
+
* debounced save cannot resurrect the pool mid-clear. Missing files are
|
|
603
|
+
* treated as a successful no-op (matches the legacy semantics).
|
|
604
|
+
*/
|
|
605
|
+
export async function clearAccountStorage(path) {
|
|
606
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
607
|
+
const lock = await acquireWithRetry(path, sleep);
|
|
608
|
+
try {
|
|
609
|
+
await unlink(path);
|
|
610
|
+
}
|
|
611
|
+
catch (error) {
|
|
612
|
+
const code = error.code;
|
|
613
|
+
if (code !== 'ENOENT') {
|
|
614
|
+
log.error('Failed to clear account storage', { error: String(error) });
|
|
615
|
+
throw error;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
finally {
|
|
619
|
+
try {
|
|
620
|
+
await lock.release();
|
|
621
|
+
}
|
|
622
|
+
catch (releaseError) {
|
|
623
|
+
log.warn('Failed to release account storage lock', {
|
|
624
|
+
error: String(releaseError),
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
export const defaultAccountStorageStore = {
|
|
630
|
+
load: loadAccountStorage,
|
|
631
|
+
saveMerged: saveAccountStorage,
|
|
632
|
+
mutate: mutateAccountStorage,
|
|
633
|
+
clear: clearAccountStorage,
|
|
634
|
+
};
|
|
635
|
+
//# sourceMappingURL=account-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-storage.js","sourceRoot":"","sources":["../src/account-storage.ts"],"names":[],"mappings":"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"}
|