@veilio-inc/cli 0.9.1 → 0.11.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.
Files changed (75) hide show
  1. package/README.md +98 -20
  2. package/dist/args.d.ts +8 -0
  3. package/dist/args.d.ts.map +1 -1
  4. package/dist/args.js +14 -0
  5. package/dist/args.js.map +1 -1
  6. package/dist/client/blocks.d.ts.map +1 -1
  7. package/dist/client/blocks.js +2 -1
  8. package/dist/client/blocks.js.map +1 -1
  9. package/dist/client/fingerprint.d.ts +4 -0
  10. package/dist/client/fingerprint.d.ts.map +1 -0
  11. package/dist/client/fingerprint.js +20 -0
  12. package/dist/client/fingerprint.js.map +1 -0
  13. package/dist/client/maps.d.ts.map +1 -1
  14. package/dist/client/maps.js +29 -8
  15. package/dist/client/maps.js.map +1 -1
  16. package/dist/client/wording.d.ts +3 -1
  17. package/dist/client/wording.d.ts.map +1 -1
  18. package/dist/client/wording.js +10 -2
  19. package/dist/client/wording.js.map +1 -1
  20. package/dist/client/wrap-judge.d.ts +30 -0
  21. package/dist/client/wrap-judge.d.ts.map +1 -0
  22. package/dist/client/wrap-judge.js +59 -0
  23. package/dist/client/wrap-judge.js.map +1 -0
  24. package/dist/cloud-commands.d.ts +21 -1
  25. package/dist/cloud-commands.d.ts.map +1 -1
  26. package/dist/cloud-commands.js +342 -5
  27. package/dist/cloud-commands.js.map +1 -1
  28. package/dist/cloud.d.ts +5 -1
  29. package/dist/cloud.d.ts.map +1 -1
  30. package/dist/cloud.js +7 -1
  31. package/dist/cloud.js.map +1 -1
  32. package/dist/commands.d.ts +3 -0
  33. package/dist/commands.d.ts.map +1 -1
  34. package/dist/commands.js +82 -47
  35. package/dist/commands.js.map +1 -1
  36. package/dist/flags.d.ts +14 -0
  37. package/dist/flags.d.ts.map +1 -1
  38. package/dist/flags.js +40 -0
  39. package/dist/flags.js.map +1 -1
  40. package/dist/git-index.d.ts +8 -0
  41. package/dist/git-index.d.ts.map +1 -0
  42. package/dist/git-index.js +161 -0
  43. package/dist/git-index.js.map +1 -0
  44. package/dist/hashed-bases.d.ts +6 -1
  45. package/dist/hashed-bases.d.ts.map +1 -1
  46. package/dist/hashed-bases.js +16 -3
  47. package/dist/hashed-bases.js.map +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +29 -19
  50. package/dist/index.js.map +1 -1
  51. package/dist/key-pins.d.ts +46 -0
  52. package/dist/key-pins.d.ts.map +1 -0
  53. package/dist/key-pins.js +165 -0
  54. package/dist/key-pins.js.map +1 -0
  55. package/dist/reservations.d.ts +6 -4
  56. package/dist/reservations.d.ts.map +1 -1
  57. package/dist/reservations.js +19 -21
  58. package/dist/reservations.js.map +1 -1
  59. package/dist/staged-blobs.d.ts +21 -0
  60. package/dist/staged-blobs.d.ts.map +1 -0
  61. package/dist/staged-blobs.js +150 -0
  62. package/dist/staged-blobs.js.map +1 -0
  63. package/dist/store.d.ts +39 -0
  64. package/dist/store.d.ts.map +1 -1
  65. package/dist/store.js +243 -24
  66. package/dist/store.js.map +1 -1
  67. package/dist/team-anonymize.d.ts +21 -4
  68. package/dist/team-anonymize.d.ts.map +1 -1
  69. package/dist/team-anonymize.js +123 -51
  70. package/dist/team-anonymize.js.map +1 -1
  71. package/dist/team-unlock.d.ts +36 -0
  72. package/dist/team-unlock.d.ts.map +1 -1
  73. package/dist/team-unlock.js +25 -1
  74. package/dist/team-unlock.js.map +1 -1
  75. package/package.json +2 -2
package/dist/store.js CHANGED
@@ -8,9 +8,11 @@
8
8
  // The map holds real identifier names, so it is written 0600 and the store
9
9
  // directory carries a .gitignore. Committing it would undo the anonymization
10
10
  // for anyone reading the repo.
11
- import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
12
- import { dirname, join, resolve } from 'node:path';
11
+ import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync, writeSync, } from 'node:fs';
12
+ import { randomBytes } from 'node:crypto';
13
+ import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
13
14
  import { STORE_DIR } from '@veilio-inc/engine';
15
+ import { trackedPaths } from './git-index.js';
14
16
  export { STORE_DIR };
15
17
  export const STORE_FILE = 'map.json';
16
18
  /** Walk up from `from` looking for an existing store or a repo root, so running
@@ -19,7 +21,11 @@ export const STORE_FILE = 'map.json';
19
21
  export function findProjectRoot(from) {
20
22
  let dir = resolve(from);
21
23
  for (;;) {
22
- if (existsSync(join(dir, STORE_DIR)) || existsSync(join(dir, '.git')))
24
+ // Another user's .veilio is not this project's store (spec 085 L2): on a
25
+ // shared machine anyone can make /tmp/.veilio.
26
+ const store = join(dir, STORE_DIR);
27
+ if ((existsSync(store) && (ownerOf(store) !== 'other' || trustedStore(store))) ||
28
+ existsSync(join(dir, '.git')))
23
29
  return dir;
24
30
  const parent = dirname(dir);
25
31
  if (parent === dir)
@@ -33,10 +39,158 @@ export function resolveMapPath(override, cwd) {
33
39
  return resolve(cwd, override);
34
40
  return join(findProjectRoot(cwd), STORE_DIR, STORE_FILE);
35
41
  }
42
+ /** The longest real name kept, as for aliases.json (reservations.ts). */
43
+ const MAX_NAME = 100_000;
44
+ // C0 and C1 controls (line feed, tab, NEL, escape, ...) and the Unicode line
45
+ // and paragraph separators. A map value is not always an identifier (a manual
46
+ // mark can be words with spaces, spec 082 adds non-ASCII letters), so no exact
47
+ // name pattern exists; a character that breaks a line or drives a terminal is
48
+ // never part of a name.
49
+ const NOT_IN_A_NAME = /[\p{Cc}\u2028\u2029]/u;
50
+ /** What a map or aliases.json may restore: 1 to 100000 characters, none of them a control or line separator. */
51
+ export function isName(v) {
52
+ return typeof v === 'string' && v.length > 0 && v.length <= MAX_NAME && !NOT_IN_A_NAME.test(v);
53
+ }
36
54
  function isSymbolMap(value) {
37
55
  if (typeof value !== 'object' || value === null || Array.isArray(value))
38
56
  return false;
39
- return Object.values(value).every((v) => typeof v === 'string');
57
+ return Object.values(value).every(isName);
58
+ }
59
+ /**
60
+ * Refuses to write a value the store would not read back (review round 1):
61
+ * a map with one would be refused whole on its next read. Refused, not
62
+ * dropped, so a pull never quietly loses a teammate's entry.
63
+ */
64
+ export function refuseNonNames(what, map) {
65
+ const bad = Object.keys(map).find((k) => !isName(map[k]));
66
+ if (bad !== undefined)
67
+ throw new StoreRefusal(`refusing to write ${what}: the value of ${bad.replace(new RegExp(NOT_IN_A_NAME.source, 'gu'), '').slice(0, 60)} is not a name (1 to 100000 characters, no control character or line break), so nothing was written.`);
68
+ }
69
+ /** A store the CLI will not use: exit 1 in the CLI, a tool error in the MCP server. */
70
+ export class StoreRefusal extends Error {
71
+ }
72
+ /**
73
+ * The one way a store file (map.json, aliases.json, reserved.json) is read
74
+ * (spec 085 R1): its text, or null when there is none. Refused, whatever the
75
+ * file: when `.veilio/` or the file is a link (a cloned repository can commit
76
+ * one to another project's map), and when git tracks `.veilio`, map.json or
77
+ * aliases.json (a map in the repository is not yours to restore from). Git is
78
+ * asked first, so a tracked map is refused even where the file is absent under
79
+ * this spelling. Outside git, or with an index this reader cannot follow, the
80
+ * tracked check cannot answer and the file is read as before.
81
+ */
82
+ export function openStoreFile(what, path) {
83
+ const dir = dirname(path);
84
+ const found = trackedStoreFile(path);
85
+ if (found !== null) {
86
+ const { root, tracked } = found;
87
+ // The path comes from the checkout: shown without control characters. A
88
+ // command only off Windows (its shells read quotes differently) and only
89
+ // for a root and path of plain characters; both single-quoted.
90
+ const shown = tracked.replace(new RegExp(NOT_IN_A_NAME.source, 'gu'), '');
91
+ const plain = /^[A-Za-z0-9._/ -]+$/;
92
+ const how = process.platform !== 'win32' && plain.test(root) && plain.test(tracked)
93
+ ? ` (\`git -C ${shellQuote(root)} rm --cached -- ${shellQuote(tracked)}\`)`
94
+ : '';
95
+ throw new StoreRefusal(`\`${shown}\` is tracked by git: a map in the repository is not yours to restore from. ` +
96
+ `Remove it from git${how}, then scrub again to build your own.`);
97
+ }
98
+ for (const p of [dir, path])
99
+ if (isLink(p))
100
+ throw new StoreRefusal(`refusing to read ${what}: ${p} is a link. The map is read only where it appears to be.`);
101
+ refuseOthers(dir, path);
102
+ if (!existsSync(path))
103
+ return null;
104
+ return readFileSync(path, 'utf8');
105
+ }
106
+ /**
107
+ * Whose `path` is: 'me' for the running user, 'other' for anyone else, 'none'
108
+ * when it is not there. Windows (no uid): always 'me'. Under sudo (root, with
109
+ * SUDO_UID), a file of the user who ran sudo is 'sudo': readable, not writable
110
+ * (security review: a file root writes there would be root's).
111
+ */
112
+ function ownerOf(path) {
113
+ const me = process.getuid?.();
114
+ let uid;
115
+ try {
116
+ uid = lstatSync(path).uid;
117
+ }
118
+ catch {
119
+ return 'none';
120
+ }
121
+ if (me === undefined || uid === me)
122
+ return 'me';
123
+ return me === 0 && process.env.SUDO_UID === String(uid) ? 'sudo' : 'other';
124
+ }
125
+ /**
126
+ * The stores VEILIO_TRUST_STORE_OWNER lists (absolute paths, separated as in
127
+ * PATH), by real path, as git's safe.directory: each one exactly, no other.
128
+ */
129
+ function trustedStore(dir) {
130
+ const listed = (process.env.VEILIO_TRUST_STORE_OWNER ?? '').split(delimiter).filter(isAbsolute);
131
+ if (listed.length === 0)
132
+ return false;
133
+ const real = (p) => {
134
+ try {
135
+ return realpathSync(p);
136
+ }
137
+ catch {
138
+ return resolve(p);
139
+ }
140
+ };
141
+ const here = real(dir);
142
+ return listed.some((p) => real(p) === here);
143
+ }
144
+ const sudoWriteRefusal = (dir) => new StoreRefusal(`refusing to write ${dir} as root: it belongs to the user who ran sudo, and a file root writes there would be root's. Run veilio without sudo.`);
145
+ /** The store directory and its file are this user's, or not used (spec 085 L2, Q2 = A). */
146
+ function refuseOthers(dir, path, write = false) {
147
+ const owners = [ownerOf(dir), ownerOf(path)];
148
+ if (owners.includes('sudo') && write && !trustedStore(dir))
149
+ throw sudoWriteRefusal(dir);
150
+ if (owners.includes('other') && !trustedStore(dir))
151
+ throw new StoreRefusal(`refusing to use ${dir}: it belongs to another user on this machine. Run veilio inside your own project, or remove that directory. If you trust it, add its full path to VEILIO_TRUST_STORE_OWNER.`);
152
+ }
153
+ /**
154
+ * Write a store file as a new file beside it, then rename it into place
155
+ * (spec 085 L2): never written through the file already there, which may be
156
+ * another name for a file elsewhere (a hard link) or another user's.
157
+ */
158
+ export function writeStoreFile(what, path, text) {
159
+ checkStoreWrite(what, path);
160
+ const tmp = join(dirname(path), `.${basename(path)}.${randomBytes(6).toString('hex')}.tmp`);
161
+ const fd = openSync(tmp, 'wx', 0o600);
162
+ try {
163
+ try {
164
+ writeSync(fd, text);
165
+ }
166
+ finally {
167
+ closeSync(fd);
168
+ }
169
+ renameSync(tmp, path);
170
+ }
171
+ catch (err) {
172
+ rmSync(tmp, { force: true });
173
+ throw err;
174
+ }
175
+ }
176
+ /** One POSIX shell word, for a string of plain characters (no quote in it). */
177
+ const shellQuote = (s) => `'${s}'`;
178
+ /** The store path git tracks, as git names it, with its work tree root; null when none, or no way to tell. */
179
+ function trackedStoreFile(path) {
180
+ const dir = dirname(path);
181
+ const git = trackedPaths(dir);
182
+ if (!git)
183
+ return null;
184
+ const rel = (p) => relative(git.root, p).split(sep).join('/');
185
+ const candidates = [path];
186
+ if (basename(dir) === STORE_DIR)
187
+ candidates.unshift(dir, join(dir, STORE_FILE), join(dir, 'aliases.json'));
188
+ for (const p of candidates) {
189
+ const name = rel(p);
190
+ if (name && !name.startsWith('..') && git.paths.has(name.toLowerCase()))
191
+ return { root: git.root, tracked: name };
192
+ }
193
+ return null;
40
194
  }
41
195
  /**
42
196
  * The Cloud provenance recorded alongside the local map, if any.
@@ -46,10 +200,11 @@ function isSymbolMap(value) {
46
200
  * `remote` — which reads correctly as "this map did not come from Cloud".
47
201
  */
48
202
  export function loadRemote(path) {
49
- if (!existsSync(path))
203
+ const text = openStoreFile('the map', path);
204
+ if (text === null)
50
205
  return undefined;
51
206
  try {
52
- const parsed = JSON.parse(readFileSync(path, 'utf8'));
207
+ const parsed = JSON.parse(text);
53
208
  const remote = parsed.remote;
54
209
  if (!remote || typeof remote.id !== 'string' || typeof remote.updatedAt !== 'string') {
55
210
  return undefined;
@@ -64,11 +219,12 @@ export function loadRemote(path) {
64
219
  * file exists but cannot be understood — silently starting from empty there
65
220
  * would orphan every placeholder the user already has in flight. */
66
221
  export function loadMap(path) {
67
- if (!existsSync(path))
222
+ const text = openStoreFile('the map', path);
223
+ if (text === null)
68
224
  return {};
69
225
  let parsed;
70
226
  try {
71
- parsed = JSON.parse(readFileSync(path, 'utf8'));
227
+ parsed = JSON.parse(text);
72
228
  }
73
229
  catch {
74
230
  throw new Error(`map file at ${path} is not valid JSON`);
@@ -100,6 +256,7 @@ export class MapOverwriteError extends Error {
100
256
  * another session's store, or by a future caller that forgets to load first.
101
257
  */
102
258
  export function saveMap(path, map, options = {}) {
259
+ refuseNonNames('the map', map);
103
260
  if (!options.force && existsSync(path)) {
104
261
  const dropped = Object.entries(loadMap(path)).filter(([placeholder, real]) => map[placeholder] !== real);
105
262
  if (dropped.length > 0) {
@@ -112,32 +269,94 @@ export function saveMap(path, map, options = {}) {
112
269
  `could never be restored. Pass --force to overwrite anyway.`);
113
270
  }
114
271
  }
115
- const dir = dirname(path);
116
- // Security audit 2026-11-01: a store that is a link (one a repository
117
- // committed) would put the real names in a file outside the project.
118
- refuseLinks('the map', dir, path);
119
- mkdirSync(dir, { recursive: true });
120
- // A store directory inside a repo must never be committed — it holds the real
121
- // names the anonymization exists to hide.
122
- const ignore = join(dir, '.gitignore');
123
- if (dir.endsWith(STORE_DIR) && !existsSync(ignore)) {
124
- writeFileSync(ignore, '*\n', { mode: 0o600 });
125
- }
272
+ prepareStoreWrite('the map', path);
126
273
  // Carried forward when the caller does not supply one, so an ordinary `scrub`
127
274
  // does not quietly erase the provenance a `pull` recorded.
128
275
  const remote = options.remote ?? loadRemote(path);
129
276
  const payload = { version: 1, map, ...(remote ? { remote } : {}) };
130
- writeFileSync(path, `${JSON.stringify(payload, null, 2)}\n`, { mode: 0o600 });
131
- // writeFileSync only applies `mode` when creating the file; enforce it on
132
- // rewrite too so a pre-existing world-readable map gets locked down.
133
- chmodSync(path, 0o600);
277
+ // A new 0600 file each time, so a world-readable map already there is replaced too.
278
+ writeStoreFile('the map', path, `${JSON.stringify(payload, null, 2)}\n`);
279
+ }
280
+ /**
281
+ * Everything that must hold before a store file is written: neither the store
282
+ * directory nor the file is a link (security audit 2026-11-01: a link a
283
+ * repository committed would put the real names outside the project), and a
284
+ * `.veilio` directory carries a `.gitignore` that keeps it out of git. One
285
+ * there already must be a plain file whose only pattern is `*` (spec 085 L4: a
286
+ * repository can commit its own, which ignores nothing); a missing one is
287
+ * written. It is never rewritten: it may be tracked, and a silent change to a
288
+ * tracked file is worse than a refusal.
289
+ */
290
+ export function prepareStoreWrite(what, path) {
291
+ const dir = dirname(path);
292
+ // Under sudo, in a project the invoking user owns, root would make a store
293
+ // that user cannot use (review round 2): refused before anything is made.
294
+ if (ownerOf(dirname(dir)) === 'sudo' && !trustedStore(dir))
295
+ throw sudoWriteRefusal(dir);
296
+ checkStoreWrite(what, path);
297
+ // Made 0700 and not recursively, so a directory already there is checked
298
+ // again rather than taken: another user may have swapped it in meanwhile.
299
+ mkdirSync(dirname(dir), { recursive: true });
300
+ try {
301
+ mkdirSync(dir, { mode: 0o700 });
302
+ }
303
+ catch (err) {
304
+ if (err.code !== 'EEXIST')
305
+ throw err;
306
+ }
307
+ checkStoreWrite(what, path);
308
+ if (basename(dir) !== STORE_DIR)
309
+ return;
310
+ const ignore = join(dir, '.gitignore');
311
+ let st;
312
+ try {
313
+ st = lstatSync(ignore);
314
+ }
315
+ catch {
316
+ // None there: written, and never through a link planted after the check.
317
+ writeFileSync(ignore, '*\n', { mode: 0o600, flag: 'wx' });
318
+ return;
319
+ }
320
+ if (!st.isFile() || !onlyStar(readFileSync(ignore, 'utf8')))
321
+ throw new StoreRefusal(`refusing to write ${what}: ${dir}/.gitignore does not keep it out of git (it must be a plain file whose only pattern is \`*\`). Fix that file, then run again.`);
322
+ }
323
+ /**
324
+ * The store directory is a real directory and neither it nor the file is a
325
+ * link or another user's. Run before mkdir, after it, and again right before
326
+ * the rename (security review). Node has no openat, so a window remains
327
+ * between the last check and the rename; the 0700 directory bounds it.
328
+ */
329
+ function checkStoreWrite(what, path) {
330
+ const dir = dirname(path);
331
+ refuseLinks(what, dir, path);
332
+ let st;
333
+ try {
334
+ st = lstatSync(dir);
335
+ }
336
+ catch {
337
+ st = null; // not made yet
338
+ }
339
+ if (st && !st.isDirectory())
340
+ throw new StoreRefusal(`refusing to write ${what}: ${dir} is not a directory`);
341
+ refuseOthers(dir, path, true);
342
+ }
343
+ /**
344
+ * A .gitignore whose only pattern is `*` (security review): `*` then
345
+ * `!map.json` would let git track the map, and the CLI cannot ask git which
346
+ * files it ignores. Blank lines and `#` comments are allowed. No trimming:
347
+ * git keeps leading spaces and a trailing tab (` *`, `*\t` match nothing), so
348
+ * only a line that is exactly `*` (CRLF accepted) counts.
349
+ */
350
+ function onlyStar(text) {
351
+ const patterns = text.split(/\r?\n/).filter((l) => l !== '' && !l.startsWith('#'));
352
+ return patterns.length > 0 && patterns.every((l) => l === '*');
134
353
  }
135
354
  /** Throws when any of `paths` is a link: the store's files are written only
136
355
  * where they appear to be (security audit 2026-11-01). */
137
356
  export function refuseLinks(what, ...paths) {
138
357
  for (const p of paths)
139
358
  if (isLink(p))
140
- throw new Error(`refusing to write ${what}: ${p} is a link`);
359
+ throw new StoreRefusal(`refusing to write ${what}: ${p} is a link`);
141
360
  }
142
361
  function isLink(path) {
143
362
  try {
package/dist/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -100,8 +100,12 @@ export declare class ReservationFailed extends Error {
100
100
  readonly cause: unknown;
101
101
  constructor(cause: unknown);
102
102
  }
103
+ /** Cloud's reserve route refuses more numbers per base, or more bases, in one request. */
104
+ export declare const RESERVE_MAX_COUNT = 5000;
105
+ export declare const RESERVE_MAX_BASES = 32;
103
106
  /**
104
- * `anonymizeOverTeam`, with every NEW number taken from the team's allocation.
107
+ * `anonymizeOverTeam` for the files of one call, with every NEW number taken
108
+ * from the team's allocation.
105
109
  *
106
110
  * Two passes, because only this machine can read the identifiers and so only
107
111
  * this machine can know how many new names there are — but it may not choose
@@ -119,13 +123,26 @@ export declare class ReservationFailed extends Error {
119
123
  * Step 4 is not belt-and-braces. If it ever fires, the alternative is a map
120
124
  * that looks correct, publishes, and collides with a teammate's — the exact
121
125
  * failure that is invisible until someone restores the wrong name.
126
+ *
127
+ * Every file of one call goes through these steps together, with one
128
+ * reservation for all of them (e40: a 164-file project made 164 reservations
129
+ * and met Cloud's rate limit) - or one per group of files when they need more
130
+ * than one request may ask. Pass 1 carries each file's names into the next, so
131
+ * a name several files share is counted once; pass 2 numbers file after file
132
+ * inside the reserved runs. A mismatch in any file fails the whole call - no
133
+ * file comes back with numbers nobody reserved.
122
134
  */
123
- export declare function reservedAnonymizeOverTeam(source: string, local: Record<string, string>, team: {
135
+ export declare function reservedAnonymizeFilesOverTeam(files: ReadonlyArray<{
136
+ source: string;
137
+ options: Omit<AnonymizeOptions, 'existingMap'>;
138
+ }>, local: Record<string, string>, team: {
124
139
  namespace: Record<string, string>;
125
140
  highest: Record<string, number>;
126
141
  conflicts?: Record<string, number>;
127
- }, options: Omit<AnonymizeOptions, 'existingMap'>, reserve: Reserve): Promise<{
128
- result: ReturnType<typeof anonymize>;
142
+ }, reserve: Reserve): Promise<{
143
+ results: ReturnType<typeof anonymize>[];
144
+ /** How many entries each file added to the store. */
145
+ added: number[];
129
146
  toPersist: Record<string, string>;
130
147
  }>;
131
148
  //# sourceMappingURL=team-anonymize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"team-anonymize.d.ts","sourceRoot":"","sources":["../src/team-anonymize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"team-anonymize.d.ts","sourceRoot":"","sources":["../src/team-anonymize.ts"],"names":[],"mappings":"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"}
@@ -192,8 +192,12 @@ export class ReservationFailed extends Error {
192
192
  this.name = 'ReservationFailed';
193
193
  }
194
194
  }
195
+ /** Cloud's reserve route refuses more numbers per base, or more bases, in one request. */
196
+ export const RESERVE_MAX_COUNT = 5000;
197
+ export const RESERVE_MAX_BASES = 32;
195
198
  /**
196
- * `anonymizeOverTeam`, with every NEW number taken from the team's allocation.
199
+ * `anonymizeOverTeam` for the files of one call, with every NEW number taken
200
+ * from the team's allocation.
197
201
  *
198
202
  * Two passes, because only this machine can read the identifiers and so only
199
203
  * this machine can know how many new names there are — but it may not choose
@@ -211,61 +215,129 @@ export class ReservationFailed extends Error {
211
215
  * Step 4 is not belt-and-braces. If it ever fires, the alternative is a map
212
216
  * that looks correct, publishes, and collides with a teammate's — the exact
213
217
  * failure that is invisible until someone restores the wrong name.
218
+ *
219
+ * Every file of one call goes through these steps together, with one
220
+ * reservation for all of them (e40: a 164-file project made 164 reservations
221
+ * and met Cloud's rate limit) - or one per group of files when they need more
222
+ * than one request may ask. Pass 1 carries each file's names into the next, so
223
+ * a name several files share is counted once; pass 2 numbers file after file
224
+ * inside the reserved runs. A mismatch in any file fails the whole call - no
225
+ * file comes back with numbers nobody reserved.
214
226
  */
215
- export async function reservedAnonymizeOverTeam(source, local, team, options, reserve) {
227
+ export async function reservedAnonymizeFilesOverTeam(files, local, team, reserve) {
216
228
  const settled = Object.fromEntries(Object.entries(team.namespace).filter(([p]) => !(p in (team.conflicts ?? {}))));
217
229
  const existingMap = mergeNamespace(local, settled);
218
- // Pass 1: count the new names per base. No floor needed — the numbers this
219
- // pass chooses are discarded.
220
- const first = anonymize(source, { ...options, existingMap });
221
- const fresh = Object.keys(first.map).filter((p) => !(p in existingMap));
222
- if (fresh.length === 0) {
223
- // Nothing new, so nothing to reserve. Returning the first pass is correct
224
- // AND is the only way to avoid a reservation of zero numbers, which the
225
- // server would answer with an empty run the verification below rejects.
226
- return { result: first, toPersist: persisted(local, first, settled) };
227
- }
228
- const counts = new Map();
229
- for (const p of fresh) {
230
- const m = NUMBERED.exec(p);
231
- if (!m)
232
- throw new ReservationMismatch(p);
233
- counts.set(m[1], (counts.get(m[1]) ?? 0) + 1);
234
- }
235
- const inMap = highestPerBase(existingMap);
236
- const inText = highestInText(source);
237
- const requests = [...counts].map(([base, count]) => ({
238
- base,
239
- count,
240
- floor: Math.max(team.highest[base] ?? 0, inMap[base] ?? 0, inText[base] ?? 0),
241
- }));
242
- let ranges;
243
- try {
244
- ranges = await reserve(requests);
245
- }
246
- catch (err) {
247
- throw new ReservationFailed(err);
230
+ // Pass 1: each file over the names the earlier ones minted, so a name several
231
+ // files share is counted once, for the first file that has it. The numbers
232
+ // this pass chooses are discarded. The engine copies the map it is given.
233
+ const seen = { ...existingMap };
234
+ const firsts = [];
235
+ const newIn = [];
236
+ for (const { source, options } of files) {
237
+ const result = anonymize(source, { ...options, existingMap: seen });
238
+ const counts = new Map();
239
+ for (const p of Object.keys(result.map)) {
240
+ if (p in seen)
241
+ continue;
242
+ const m = NUMBERED.exec(p);
243
+ if (!m)
244
+ throw new ReservationMismatch(p);
245
+ counts.set(m[1], (counts.get(m[1]) ?? 0) + 1);
246
+ }
247
+ Object.assign(seen, result.map);
248
+ firsts.push(result);
249
+ newIn.push(counts);
248
250
  }
249
- const byBase = new Map(ranges.map((r) => [r.base, r]));
250
- // Pass 2: `start - 1` as the floor, so the first new number IS `start`.
251
- const floors = {};
252
- for (const { base } of requests) {
253
- const range = byBase.get(base);
254
- if (!range || !isSaneBlock(range))
255
- throw new ReservationMismatch(`${base}*`);
256
- floors[base] = range.start - 1;
257
- }
258
- const second = anonymizeAbove(source, { ...options, existingMap }, floors);
259
- for (const placeholder of Object.keys(second.map)) {
260
- if (placeholder in existingMap)
261
- continue;
262
- const m = NUMBERED.exec(placeholder);
263
- const range = m ? byBase.get(m[1]) : undefined;
264
- const n = m ? Number(m[2]) : NaN;
265
- if (!range || n < range.start || n > range.end)
266
- throw new ReservationMismatch(placeholder);
251
+ /** The store after each result, and how many entries each added. */
252
+ const keep = (results) => {
253
+ let toPersist = local;
254
+ const added = results.map((result) => {
255
+ const before = Object.keys(toPersist).length;
256
+ toPersist = persisted(toPersist, result, settled);
257
+ return Object.keys(toPersist).length - before;
258
+ });
259
+ return { results, added, toPersist };
260
+ };
261
+ // Nothing new, so nothing to reserve. Returning the first pass is correct AND
262
+ // is the only way to avoid a reservation of zero numbers, which the server
263
+ // would answer with an empty run the verification below rejects.
264
+ if (newIn.every((c) => c.size === 0))
265
+ return keep(firsts);
266
+ // Files in groups, each within one request's limits - one group, one
267
+ // reservation, for any project short of thousands of new names per base.
268
+ // A single file over a limit cannot be split: it fails here, with the reason.
269
+ const groups = [];
270
+ newIn.forEach((counts, i) => {
271
+ const over = [...counts].find(([, n]) => n > RESERVE_MAX_COUNT);
272
+ if (over || counts.size > RESERVE_MAX_BASES)
273
+ throw new ReservationFailed(new Error(over
274
+ ? `one file needs ${over[1]} new ${over[0]} names, more than the ${RESERVE_MAX_COUNT} one reservation may ask - scrub it in parts`
275
+ : `one file needs new names in ${counts.size} kinds, more than the ${RESERVE_MAX_BASES} one reservation may ask - scrub it in parts`));
276
+ const last = groups.at(-1);
277
+ const fits = last !== undefined &&
278
+ [...counts].every(([base, n]) => (last.counts.get(base) ?? 0) + n <= RESERVE_MAX_COUNT) &&
279
+ new Set([...last.counts.keys(), ...counts.keys()]).size <= RESERVE_MAX_BASES;
280
+ if (last && fits) {
281
+ for (const [base, n] of counts)
282
+ last.counts.set(base, (last.counts.get(base) ?? 0) + n);
283
+ last.to = i + 1;
284
+ }
285
+ else
286
+ groups.push({ from: i, to: i + 1, counts: new Map(counts) });
287
+ });
288
+ // A number already taken - in this project's store (also one the merge with
289
+ // the team's namespace left out), or in any file's text - is below every floor.
290
+ const taken = highestPerBase(local);
291
+ for (const { source } of files)
292
+ for (const [base, n] of Object.entries(highestInText(source)))
293
+ if (n > (taken[base] ?? 0))
294
+ taken[base] = n;
295
+ const map = { ...existingMap };
296
+ const results = [];
297
+ for (const group of groups) {
298
+ const inMap = highestPerBase(map);
299
+ const requests = [...group.counts].map(([base, count]) => ({
300
+ base,
301
+ count,
302
+ floor: Math.max(team.highest[base] ?? 0, inMap[base] ?? 0, taken[base] ?? 0),
303
+ }));
304
+ let ranges = [];
305
+ if (requests.length > 0) {
306
+ try {
307
+ ranges = await reserve(requests);
308
+ }
309
+ catch (err) {
310
+ throw new ReservationFailed(err);
311
+ }
312
+ }
313
+ const byBase = new Map(ranges.map((r) => [r.base, r]));
314
+ // Pass 2: `start - 1` as the floor, so the first new number IS `start`;
315
+ // each later file of the group numbers above the earlier ones, inside the run.
316
+ const floors = {};
317
+ for (const { base } of requests) {
318
+ const range = byBase.get(base);
319
+ if (!range || !isSaneBlock(range))
320
+ throw new ReservationMismatch(`${base}*`);
321
+ floors[base] = range.start - 1;
322
+ }
323
+ const before = new Set(Object.keys(map));
324
+ for (let i = group.from; i < group.to; i++) {
325
+ const result = anonymizeAbove(files[i].source, { ...files[i].options, existingMap: map }, floors);
326
+ Object.assign(map, result.map);
327
+ results.push(result);
328
+ }
329
+ // Every new placeholder of the group - none expected where nothing was reserved.
330
+ for (const placeholder of Object.keys(map)) {
331
+ if (before.has(placeholder))
332
+ continue;
333
+ const m = NUMBERED.exec(placeholder);
334
+ const range = m ? byBase.get(m[1]) : undefined;
335
+ const n = m ? Number(m[2]) : NaN;
336
+ if (!range || n < range.start || n > range.end)
337
+ throw new ReservationMismatch(placeholder);
338
+ }
267
339
  }
268
- return { result: second, toPersist: persisted(local, second, settled) };
340
+ return keep(results);
269
341
  }
270
342
  /** What the project's store keeps: everything it held, whatever was minted, and
271
343
  * only the team entries the output actually used (spec 005 US4). Shared with