@veilio-inc/cli 0.7.1 → 0.9.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 (67) hide show
  1. package/README.md +157 -14
  2. package/dist/client/blocks.d.ts +30 -0
  3. package/dist/client/blocks.d.ts.map +1 -0
  4. package/dist/client/blocks.js +125 -0
  5. package/dist/client/blocks.js.map +1 -0
  6. package/dist/client/maps.d.ts +8 -0
  7. package/dist/client/maps.d.ts.map +1 -1
  8. package/dist/client/maps.js +260 -16
  9. package/dist/client/maps.js.map +1 -1
  10. package/dist/client/rules-skipped.d.ts +22 -0
  11. package/dist/client/rules-skipped.d.ts.map +1 -0
  12. package/dist/client/rules-skipped.js +30 -0
  13. package/dist/client/rules-skipped.js.map +1 -0
  14. package/dist/client/wording.d.ts +2 -2
  15. package/dist/client/wording.d.ts.map +1 -1
  16. package/dist/client/wording.js +15 -0
  17. package/dist/client/wording.js.map +1 -1
  18. package/dist/cloud-commands.d.ts +5 -3
  19. package/dist/cloud-commands.d.ts.map +1 -1
  20. package/dist/cloud-commands.js +109 -28
  21. package/dist/cloud-commands.js.map +1 -1
  22. package/dist/cloud.d.ts +74 -7
  23. package/dist/cloud.d.ts.map +1 -1
  24. package/dist/cloud.js +205 -3
  25. package/dist/cloud.js.map +1 -1
  26. package/dist/commands.d.ts +10 -0
  27. package/dist/commands.d.ts.map +1 -1
  28. package/dist/commands.js +90 -15
  29. package/dist/commands.js.map +1 -1
  30. package/dist/credential.d.ts +12 -0
  31. package/dist/credential.d.ts.map +1 -1
  32. package/dist/credential.js +48 -0
  33. package/dist/credential.js.map +1 -1
  34. package/dist/flags.js +2 -2
  35. package/dist/flags.js.map +1 -1
  36. package/dist/hashed-bases.d.ts +12 -0
  37. package/dist/hashed-bases.d.ts.map +1 -0
  38. package/dist/hashed-bases.js +45 -0
  39. package/dist/hashed-bases.js.map +1 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +1 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/reservations.d.ts +145 -0
  44. package/dist/reservations.d.ts.map +1 -0
  45. package/dist/reservations.js +348 -0
  46. package/dist/reservations.js.map +1 -0
  47. package/dist/rules-open.d.ts +16 -0
  48. package/dist/rules-open.d.ts.map +1 -0
  49. package/dist/rules-open.js +87 -0
  50. package/dist/rules-open.js.map +1 -0
  51. package/dist/rules.d.ts +20 -2
  52. package/dist/rules.d.ts.map +1 -1
  53. package/dist/rules.js +86 -4
  54. package/dist/rules.js.map +1 -1
  55. package/dist/store.d.ts +3 -0
  56. package/dist/store.d.ts.map +1 -1
  57. package/dist/store.js +19 -1
  58. package/dist/store.js.map +1 -1
  59. package/dist/team-anonymize.d.ts +16 -1
  60. package/dist/team-anonymize.d.ts.map +1 -1
  61. package/dist/team-anonymize.js +39 -13
  62. package/dist/team-anonymize.js.map +1 -1
  63. package/dist/team-namespace.d.ts +59 -4
  64. package/dist/team-namespace.d.ts.map +1 -1
  65. package/dist/team-namespace.js +133 -11
  66. package/dist/team-namespace.js.map +1 -1
  67. package/package.json +7 -5
package/README.md CHANGED
@@ -30,7 +30,7 @@ signed-in `scrub` offline, `veilio logout` first.
30
30
  | Command | Purpose |
31
31
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32
32
  | `scrub [files...]` | Mask identifiers, redact credentials. Reads stdin when given no file. |
33
- | `restore [files...]` | Swap placeholders back, strip AI-generated noise. Signed in, also a teammate's placeholders — see below. Names anything it could not restore; `--strict` writes nothing if a placeholder would be left. |
33
+ | `restore [files...]` | Swap placeholders back, strip AI-generated noise. Signed in, also a teammate's placeholders — see below. Names anything it could not restore, a redacted value included; `--strict` writes nothing if a placeholder or a redaction would be left. |
34
34
  | `scan [files...]` | Detect credentials only. Never rewrites. Exits 1 on a credential; with `--strict`, on any finding. |
35
35
  | `map` | Show the symbol map (`--clear` to wipe it). |
36
36
 
@@ -49,9 +49,9 @@ veilio maps rm <id> # remove a map from Cloud
49
49
  veilio projects # the projects your team works in; * marks the one in use
50
50
  veilio projects use <name> # work in that project (kept with the sign-in)
51
51
  veilio team unlock # open the team key with your vault passphrase (kept 7 days)
52
- veilio team lock # remove the unlocked team key from this machine
52
+ veilio team lock # remove the unlocked team key, and the team rules, from this machine
53
53
  veilio vault unlock # keep the personal-maps key here (7 days), for the MCP server
54
- veilio vault lock # remove it from this machine
54
+ veilio vault lock # remove it, and the personal rules, from this machine
55
55
  veilio rules pull # fetch your custom rules; scrub then applies them offline
56
56
  veilio logout # revokes server-side, then removes the local credential
57
57
  ```
@@ -119,6 +119,54 @@ Custom rules (whitelist and replace, set in the web app) are applied by
119
119
  offline - and says on every run how many rules it applied and how old the copy
120
120
  is. Pull again after the rules change; `logout` removes the copy.
121
121
 
122
+ Cloud holds the rules sealed under your keys, so it cannot read them: personal
123
+ rules under your personal-maps key, team rules under your team key. `rules pull`
124
+ opens them on this machine, so it needs `veilio vault unlock` for personal rules
125
+ and `veilio team unlock` for team rules. A rule it cannot open is skipped, never
126
+ an error: `scrub` still masks, with the built-in engine and the rules that did
127
+ open, and both commands say what was skipped and how to fix it, one sentence per
128
+ cause (on every `scrub`, `--quiet` included).
129
+
130
+ The opened rules last only as long as the key they were opened with.
131
+ `veilio vault lock` removes the personal rules from `rules.json`, and
132
+ `veilio team lock` the team rules, until the next unlock and `rules pull`; both
133
+ say how many they removed, and the copy counts them as vault locked or team key
134
+ locked. A key that expires, or is deleted by hand, has the same effect without
135
+ a lock: `scrub` and the MCP server apply a cached rule only while its key is
136
+ still on this machine, unexpired and for this account. A `rules pull` while
137
+ locked does not bring them back:
138
+
139
+ ```
140
+ 2 custom rules not applied: vault locked - run `veilio vault unlock`, then `veilio rules pull`.
141
+ 1 custom rule not applied: team key locked - run `veilio team unlock`, then `veilio rules pull`.
142
+ 1 custom rule not applied: could not be opened with the keys on this machine, and skipped.
143
+ 1 custom rule not applied: refused as unsafe to apply (an engine placeholder or a pattern rules do not support), and skipped.
144
+ ```
145
+
146
+ When some rules applied and others did not, `scrub` says both in one line:
147
+
148
+ ```
149
+ veilio: applied 1 custom rule pulled just now; 2 not applied: vault locked - run `veilio vault unlock`, then `veilio rules pull`.
150
+ ```
151
+
152
+ Under `--quiet` it prints only what was not applied, in the sentences above.
153
+
154
+ "Could not be opened" is a rule sealed under a team-key version this machine
155
+ does not hold (run `veilio team unlock` again after a rotation) or a damaged
156
+ one. "Refused" is a rule no tool applies, whoever wrote it: a replace
157
+ placeholder that reuses an engine base such as `__FN__`, a pattern the rule
158
+ matcher does not support (a backreference, lookaround, `\b`, or a bound over
159
+ 50), or a sealed body moved to another rule's row.
160
+
161
+ One `scrub` of one input spends a bounded amount of matching work on custom
162
+ rules, all rules and names together. Rules that would take more stop matching
163
+ part-way - the names after that point are masked as usual, none kept readable
164
+ or given a rule's placeholder - and `scrub` says so, under `--quiet` too:
165
+
166
+ ```
167
+ veilio: custom rules stopped matching: too much work. Names after that point were masked as usual, and no rule kept one readable or gave it a rule placeholder.
168
+ ```
169
+
122
170
  Four files, all `0600`, all under `~/.veilio/`: `credential.json` (the session
123
171
  and the chosen project, removed by `logout`), `rules.json` (the rules copy),
124
172
  `team-keys.json` (the keys `team unlock` opened, kept seven days) and
@@ -129,17 +177,90 @@ removes all of them.
129
177
 
130
178
  Signed in to a team with the team key unlocked, `veilio scrub` numbers from the
131
179
  team's maps, as the web app and the MCP server do: a name the team already knows
132
- gets the team's placeholder, and a new name is numbered above the team's and
133
- this project's highest, so it can never take a number that means something else
134
- to a teammate. Only the team entries the output uses are kept in this project's
135
- map. The summary says `Namespace: team`.
180
+ gets the team's placeholder, and a new name is numbered inside this checkout's
181
+ block of team numbers (`.veilio/reserved.json`, below) - or, with no usable
182
+ block, in this checkout's local family `__LOCAL_<TAG>_<KIND>__n` - so it can
183
+ never take a number that means something else to a teammate. It is never
184
+ numbered above the team's highest: that is where the next teammate's block
185
+ starts. Only the team entries the output uses are kept in this project's map.
186
+ The summary says `Namespace: team`. `scrub` only reads `reserved.json`; it never
187
+ reserves, except with `--team`.
136
188
 
137
189
  - **Locked or unreachable, it still masks** — from this project's map — and says
138
- so on stderr, with the reason, even under `--quiet`: those placeholders may
139
- clash with the team's.
190
+ so on stderr, with the reason, even under `--quiet`. It is still a team, so
191
+ new names go into the local family (`__LOCAL_<TAG>_…`), never above the
192
+ map. The team comes from the team unlock, else from `~/.veilio/team.json`
193
+ (the team this account was last seen in, written by any command that lists
194
+ it and removed by `veilio logout`); with no `reserved.json` yet, scrub writes
195
+ one holding a fresh tag. With no team ever seen, new names still go into a
196
+ local family, under a tag for that run only.
140
197
  - **Signed out, it makes no request**, exactly as before. Signed in, it waits at
141
198
  most **5 seconds** for Cloud.
142
199
 
200
+ ### Team numbers for the guard
201
+
202
+ The Claude Code guard makes no request, so it cannot ask the team for a number
203
+ each time it masks a new name. Instead, `veilio maps pull` of a team map (and
204
+ `veilio team unlock` in a project that already has a map) reserves a **block**
205
+ of the team's numbers for you - 500 per kind - and keeps it in
206
+ `.veilio/reserved.json`. The guard numbers new names inside it, so two members
207
+ working at the same time never give one placeholder two meanings. A pull takes
208
+ a new block whenever a teammate's newer numbers sit above yours.
209
+
210
+ A reservation sends Cloud a kind, a count and a floor - never a name. The
211
+ engine's own kinds (`__VAR__`, `__FN__`, `__CLS__`, ...) go as they are; a
212
+ custom replace rule's placeholder (`__ACME_ACQUISITION_TARGET__`) names what
213
+ the team considers sensitive, so it is sent as `__H_<16 hex>__`, an HMAC of it
214
+ under the newest team key, and read back locally. Teammates holding the same
215
+ key send the same hash. Cloud counts each hash on its own, so a rule's kind is
216
+ floored above the team's reservations of it under its hash with every team key
217
+ version this machine holds (read from the team's reservations, which are only
218
+ ever asked for by hash): after a key rotation new numbers stay above the old
219
+ hash's while the old key is still held; without it, the floor is the map's.
220
+ Without the team key unlocked, or without that listing (an older instance),
221
+ numbers for a rule's kind are not reserved at all.
222
+
223
+ Only numbers Cloud issued count toward a floor. A number in a map that no run
224
+ of the team's reservations holds - one numbered on this machine, or planted -
225
+ is checked against the team's listing of its kind (`?bases=`, with each kind's
226
+ highest number) and floors nothing; for a kind never reserved yet, a map's
227
+ numbers floor its first run up to 10000. A pull says how many such numbers the
228
+ map held, and restore leaves one above the highest number Cloud has issued for
229
+ its kind. (A map from before team numbering with numbers above 10000, in a kind
230
+ never reserved, therefore floors nothing; such teams existed only on staging.)
231
+ Every reservation asks for an answer per kind: a kind Cloud refuses is numbered
232
+ on this machine (`__LOCAL_…`), with the refusal shown, and the others are
233
+ reserved. An older Cloud that refuses the whole call names the kinds it
234
+ refuses, and is asked again without them.
235
+
236
+ If no block can be reserved - the day's limit, offline, the plan, a server
237
+ error - the pull (or the unlock) still succeeds, exits 0, and says so on its
238
+ normal output, with the reason and, for the day's limit, when the next block is
239
+ possible:
240
+
241
+ ```
242
+ veilio: could not reserve team numbers: this account's daily limit for this team is reached; the next block is possible at 09:14 (local time). New names are numbered on this machine as __LOCAL_K7Q2XA_… until a block is held; your next publish gives them team numbers.
243
+ ```
244
+
245
+ `reserved.json` is still written, with the reason, and a signed-in
246
+ `veilio scrub` repeats the sentence on stderr - even under `--quiet` - for as
247
+ long as it holds. Until a block is held, the guard, a signed-in
248
+ `veilio scrub` and the MCP server number new names in this checkout's **local
249
+ family**, `__LOCAL_<TAG>_<KIND>__n` (`__LOCAL_K7Q2XA_VAR__3`). The tag is six
250
+ characters drawn for this checkout, so two checkouts never mint the same
251
+ string:
252
+
253
+ - **This machine restores them**, from its map.
254
+ - **A teammate's restore leaves them as written** and names them: only the
255
+ checkout that numbered one knows what it means.
256
+ - **The next team publish renumbers them** into reserved team numbers, keeps
257
+ the old placeholders in `.veilio/aliases.json` (they still restore here),
258
+ and draws a new tag.
259
+ - **No team map ever holds one.** A team map is sealed on your machine, so the
260
+ check is here too: a publish that would still seal one is refused, naming
261
+ them, and a reader drops one it finds - `maps pull` of a team map leaves
262
+ them out of `map.json` and says how many.
263
+
143
264
  ### Restoring a teammate's placeholders
144
265
 
145
266
  `veilio restore` resolves a placeholder this project's map cannot explain
@@ -151,6 +272,11 @@ with the real names:
151
272
  wins and the placeholder stays in the output with a line naming it. Same for
152
273
  one this project numbered on its own while the team was out of reach — a
153
274
  wrong name restored silently is worse than a placeholder left visibly.
275
+ - **Another checkout's local placeholder is left.** `__LOCAL_<TAG>_…` was
276
+ numbered on a checkout that held no team numbers; only that checkout restores
277
+ it, so it stays in the output, is named, and counts as left for `--strict`.
278
+ Your own restore still reads it, through `.veilio/aliases.json` once a publish
279
+ renumbered it.
154
280
  - **Locked, and it says so.** With no team key on this machine it tells you to
155
281
  run `veilio team unlock` rather than restoring half the text.
156
282
  - **Signed out, it makes no request at all** — that restore is as offline as it
@@ -176,11 +302,12 @@ a plan feature the web app couldn't.
176
302
  For: scrub
177
303
  -m, --map <path> Use a specific map file
178
304
  For: scrub, restore, map, maps pull, maps push, maps
179
- update
305
+ update, team unlock
180
306
  --json Machine-readable output
181
307
  For: scan, map
182
308
  --strict scan: also fail on advisory findings. restore: write
183
- nothing and exit 1 if a placeholder would be left
309
+ nothing and exit 1 if a placeholder or a redaction
310
+ would be left
184
311
  For: scan, restore
185
312
  --keep-docs Keep JSDoc blocks the model wrote
186
313
  For: restore
@@ -222,8 +349,9 @@ command.
222
349
  placeholder would be left in it — one the AI invented, one whose shape it changed
223
350
  (`__fn__1`), one the team's maps disagree on, or one the team's maps could not be
224
351
  read for — nothing goes to stdout and it exits 1. Without it, restore writes the
225
- text, placeholders and all, names each one on stderr and exits 0. A credential
226
- redacted on purpose is not a placeholder and never fails it.
352
+ text, placeholders and all, names each one on stderr and exits 0. A value
353
+ redacted one-way (`__REDACTED_CREDENTIAL_1__`) cannot be restored, so the text is
354
+ not the original file: restore names it every time, and `--strict` refuses it.
227
355
 
228
356
  `--keep-docs` is worth knowing about: the default strip removes JSDoc along with
229
357
  the narration and TODOs, which is wrong when the model was _asked_ to document
@@ -259,7 +387,7 @@ so write files from PowerShell 7 (`pwsh`).
259
387
  | Code | Meaning |
260
388
  | ---- | ------------------------------------------------------------------------------------------------------------------ |
261
389
  | 0 | Clean |
262
- | 1 | Findings that should stop the pipeline: a credential (`scan`), or a placeholder `restore --strict` would have left |
390
+ | 1 | Findings that should stop the pipeline: a credential (`scan`), or a placeholder or redaction `restore --strict` would have left |
263
391
  | 2 | Usage or IO error |
264
392
 
265
393
  As a pre-commit hook:
@@ -272,6 +400,21 @@ git diff --cached | veilio scan || {
272
400
  }
273
401
  ```
274
402
 
403
+ ## What is masked
404
+
405
+ Distinctive names - `quaywardThrottle`, `SkerryTariff`, `berth_quorum`, an invented
406
+ `tarnwick` - become placeholders. A name that is a single common English word
407
+ (`total`, `ledger`, `invoice`), shared vocabulary every codebase has (`src`,
408
+ `util`, `com`, `java`) or a toolchain's name (`vitest`, `junit`, `mvn`) is left as
409
+ written as a name or a path segment: it is nobody's secret, and masking it made
410
+ paths and test output unreadable. A codename that is an ordinary word (`phoenix`)
411
+ is therefore readable as a name; a custom replace rule (`veilio rules pull`) keeps
412
+ it masked. In a value - a string literal, a config value, XML text - every word is
413
+ masked. A value whose key contains a credential word (`password: sunshine`,
414
+ `DB_PASSWORD_PROD="sunshine"`, `const DB_PASS = "Summer2024!"`) is redacted one-way,
415
+ whole, under the default `--secrets redact`, so the map never holds it. Credentials
416
+ are redacted whatever they are called.
417
+
275
418
  ## The symbol map
276
419
 
277
420
  `scrub` writes `.veilio/map.json` at the project root and `restore` reads it, so placeholders stay stable across runs and across a whole session. The store is created `0600` with its own `.gitignore` — it holds the real identifier names, so committing it would undo the anonymization for anyone reading the repo.
@@ -0,0 +1,30 @@
1
+ import { type PlaceholderReservation } from '../cloud.js';
2
+ import type { Credential } from '../credential.js';
3
+ import { type Block, type RefusalReason } from '../reservations.js';
4
+ export type BlocksOutcome = {
5
+ status: 'kept';
6
+ } | {
7
+ status: 'reserved';
8
+ blocks: Record<string, Block>;
9
+ }
10
+ /** The pull still succeeded; new names are numbered in the local family
11
+ * until a block is held (spec 066). */
12
+ | {
13
+ status: 'failed';
14
+ reason: RefusalReason;
15
+ detail: string;
16
+ nextAt?: string;
17
+ tag: string;
18
+ };
19
+ /**
20
+ * Written on every outcome (spec 066 R4): without the file a refused member's
21
+ * guard cannot tell "team, no block" from "no team", and numbers into the next
22
+ * teammate's block. The checkout's tag is drawn once and kept across pulls.
23
+ */
24
+ export declare function ensureBlocks(credential: Credential, teamId: string, mapPath: string,
25
+ /** Where the team keys are: a rule's base is reserved under its hash. */
26
+ home?: string,
27
+ /** The team's reservations of the map's bases, when the caller listed
28
+ * them; null when the instance keeps no record. */
29
+ reservations?: PlaceholderReservation[] | null): Promise<BlocksOutcome>;
30
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/client/blocks.ts"],"names":[],"mappings":"AASA,OAAO,EAAmC,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAE1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,EAML,KAAK,KAAK,EACV,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAA;AAE3B,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;CAAE;AACvD;wCACwC;GACtC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAW7F;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;AACf,yEAAyE;AACzE,IAAI,CAAC,EAAE,MAAM;AACb;oDACoD;AACpD,YAAY,CAAC,EAAE,sBAAsB,EAAE,GAAG,IAAI,GAC7C,OAAO,CAAC,aAAa,CAAC,CAmGxB"}
@@ -0,0 +1,125 @@
1
+ // Spec 063 US1: make sure this member holds a block of the team's numbers for
2
+ // every kind the guard will mint, above everything the project's map holds.
3
+ //
4
+ // The guard makes no request (spec 017's rule, kept): it numbers inside the
5
+ // block offline. Whoever writes the map from Cloud - a pull, an unlock - is
6
+ // what keeps the block usable, because the engine numbers above the map's
7
+ // highest number of a kind and never into a gap below it.
8
+ import { highestPerKind, isSaneBlock } from '@veilio-inc/engine';
9
+ import { reservePlaceholders, CloudError } from '../cloud.js';
10
+ import { teamKeyBytes, teamKeyVersion } from '../hashed-bases.js';
11
+ import { loadMap } from '../store.js';
12
+ import { CORE_BASES, basesNeedingBlocks, drawTag, loadReserved, saveReserved, } from '../reservations.js';
13
+ /** Why a reservation failed, in the four kinds a member can act on (spec 066 R4). */
14
+ function reasonOf(err) {
15
+ if (!(err instanceof CloudError))
16
+ return 'server';
17
+ if (err.kind === 'unentitled')
18
+ return 'payment';
19
+ if (err.kind === 'unreachable')
20
+ return 'offline';
21
+ if (err.status === 429 && err.body?.reason === 'cap')
22
+ return 'cap';
23
+ return 'server';
24
+ }
25
+ /**
26
+ * Written on every outcome (spec 066 R4): without the file a refused member's
27
+ * guard cannot tell "team, no block" from "no team", and numbers into the next
28
+ * teammate's block. The checkout's tag is drawn once and kept across pulls.
29
+ */
30
+ export async function ensureBlocks(credential, teamId, mapPath,
31
+ /** Where the team keys are: a rule's base is reserved under its hash. */
32
+ home,
33
+ /** The team's reservations of the map's bases, when the caller listed
34
+ * them; null when the instance keeps no record. */
35
+ reservations) {
36
+ let held;
37
+ try {
38
+ held = loadReserved(mapPath);
39
+ }
40
+ catch {
41
+ held = null; // malformed: replaced, never numbered from
42
+ }
43
+ // Blocks taken by another account, team or instance are not this member's,
44
+ // and neither is the tag: two checkouts must never share one.
45
+ const same = held !== null &&
46
+ held.instance === credential.instance &&
47
+ held.account === credential.account &&
48
+ held.teamId === teamId;
49
+ let mine = same ? held.blocks : {};
50
+ const tag = (same && held.local?.tag) || drawTag();
51
+ const save = (blocks, refused) => saveReserved(mapPath, {
52
+ version: 1,
53
+ instance: credential.instance,
54
+ account: credential.account,
55
+ teamId,
56
+ blocks,
57
+ local: { tag },
58
+ ...(refused ? { refused } : {}),
59
+ });
60
+ const fail = (reason, detail, nextAt) => {
61
+ const short = detail.slice(0, 200);
62
+ save(mine, {
63
+ reason,
64
+ at: new Date().toISOString(),
65
+ ...(nextAt ? { nextAt } : {}),
66
+ detail: short,
67
+ });
68
+ return { status: 'failed', reason, detail: short, ...(nextAt ? { nextAt } : {}), tag };
69
+ };
70
+ const map = loadMap(mapPath);
71
+ const need = basesNeedingBlocks(map, mine, CORE_BASES);
72
+ if (need.length === 0 && same) {
73
+ save(mine); // adds a tag to an older file, and clears a refusal nothing needs now
74
+ return { status: 'kept' };
75
+ }
76
+ // Keyed by base: a local kind's numbers are another family and floor nothing.
77
+ const floors = highestPerKind(map);
78
+ let ranges = [];
79
+ // A rule base the server's key version refuses (Cloud 809444d0): no block
80
+ // for it, the engine bases' blocks kept, and the refusal on the band.
81
+ let refused;
82
+ if (need.length) {
83
+ try {
84
+ let sent;
85
+ ({
86
+ ranges,
87
+ refused,
88
+ floors: sent,
89
+ } = await reservePlaceholders(credential, teamId, need.map((base) => ({ base, count: 1, floor: floors[base] ?? 0 })), undefined, {
90
+ block: true,
91
+ keys: teamKeyBytes(credential, home, teamId),
92
+ keyVersion: teamKeyVersion(credential, home, teamId),
93
+ ...(reservations !== undefined ? { reservations } : {}),
94
+ }));
95
+ // Round 4 (D): the floor the server was sent, once vouched.
96
+ Object.assign(floors, sent ?? {});
97
+ }
98
+ catch (err) {
99
+ const retry = err instanceof CloudError ? err.body?.retry_at : undefined;
100
+ const nextAt = typeof retry === 'string' && !Number.isNaN(Date.parse(retry)) ? retry : undefined;
101
+ return fail(reasonOf(err), err instanceof CloudError ? err.message : String(err), nextAt);
102
+ }
103
+ }
104
+ // A reply that is not one sane run per kind asked for is no block: the
105
+ // guard would otherwise number from whatever it said.
106
+ const asked = need.filter((base) => !refused?.bases.includes(base));
107
+ const sane = Array.isArray(ranges) &&
108
+ ranges.length === asked.length &&
109
+ ranges.every((r) => asked.includes(r?.base) && isSaneBlock(r) && r.start > (floors[r.base] ?? 0));
110
+ if (!sane)
111
+ return fail('server', 'the server answered without a usable block');
112
+ const blocks = { ...mine };
113
+ for (const r of ranges)
114
+ blocks[r.base] = { start: r.start, end: r.end };
115
+ if (refused) {
116
+ mine = blocks;
117
+ return fail('server', refused.detail);
118
+ }
119
+ save(blocks);
120
+ return {
121
+ status: 'reserved',
122
+ blocks: Object.fromEntries(ranges.map((r) => [r.base, { start: r.start, end: r.end }])),
123
+ };
124
+ }
125
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/client/blocks.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type BlocksOutcome } from './blocks.js';
1
2
  import { type Env } from './project-scope.js';
2
3
  import { type Outcome } from './wording.js';
3
4
  export interface ClientContext {
@@ -40,6 +41,13 @@ export declare function pullCloudMap(ctx: ClientContext, id: string | null, opts
40
41
  name: string;
41
42
  count: number;
42
43
  path: string;
44
+ blocks?: BlocksOutcome;
45
+ /** Local-family keys the team map held and the pull left out (spec 066). */
46
+ localDropped?: number;
47
+ /** Keys numbered above 1e8: kept, never numbered after (security audit). */
48
+ outOfRange?: number;
49
+ /** Round 4 (D): keys outside every run the server issued: no floor. */
50
+ unvouched?: number;
43
51
  }>>;
44
52
  /**
45
53
  * Placeholders the local map and the team's namespace use for DIFFERENT names.
@@ -1 +1 @@
1
- {"version":3,"file":"maps.d.ts","sourceRoot":"","sources":["../../src/client/maps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"maps.d.ts","sourceRoot":"","sources":["../../src/client/maps.ts"],"names":[],"mappings":"AAmEA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAU9D,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAiC,KAAK,OAAO,EAAgB,MAAM,cAAc,CAAA;AAExF,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAClC;;;OAGG;IACH,GAAG,CAAC,EAAE,GAAG,CAAA;CACV;AAuBD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;8DAC0D;IAC1D,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAC9D,OAAO,CAAC;IACN,IAAI,EAAE,SAAS,EAAE,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,8EAA8E;IAC9E,cAAc,EAAE,OAAO,CAAA;CACxB,CAAC,CACH,CA0BA;AA8KD,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GACzC,OAAO,CACR,OAAO,CAAC;IACN,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CACH,CAqIA;AAID;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAOzD;AAkSD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,6EAA6E;AAC7E,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAsG3B;AA0BD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CA2K3B;AAwCD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,aAAa,EAClB,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC,CAyCvD"}