@veilio-inc/cli 0.7.1 → 0.9.1

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 (71) hide show
  1. package/README.md +175 -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/guard-hint.d.ts +12 -0
  37. package/dist/guard-hint.d.ts.map +1 -0
  38. package/dist/guard-hint.js +38 -0
  39. package/dist/guard-hint.js.map +1 -0
  40. package/dist/hashed-bases.d.ts +12 -0
  41. package/dist/hashed-bases.d.ts.map +1 -0
  42. package/dist/hashed-bases.js +45 -0
  43. package/dist/hashed-bases.js.map +1 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +9 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/reservations.d.ts +145 -0
  48. package/dist/reservations.d.ts.map +1 -0
  49. package/dist/reservations.js +348 -0
  50. package/dist/reservations.js.map +1 -0
  51. package/dist/rules-open.d.ts +16 -0
  52. package/dist/rules-open.d.ts.map +1 -0
  53. package/dist/rules-open.js +87 -0
  54. package/dist/rules-open.js.map +1 -0
  55. package/dist/rules.d.ts +20 -2
  56. package/dist/rules.d.ts.map +1 -1
  57. package/dist/rules.js +86 -4
  58. package/dist/rules.js.map +1 -1
  59. package/dist/store.d.ts +3 -0
  60. package/dist/store.d.ts.map +1 -1
  61. package/dist/store.js +19 -1
  62. package/dist/store.js.map +1 -1
  63. package/dist/team-anonymize.d.ts +16 -1
  64. package/dist/team-anonymize.d.ts.map +1 -1
  65. package/dist/team-anonymize.js +39 -13
  66. package/dist/team-anonymize.js.map +1 -1
  67. package/dist/team-namespace.d.ts +59 -4
  68. package/dist/team-namespace.d.ts.map +1 -1
  69. package/dist/team-namespace.js +133 -11
  70. package/dist/team-namespace.js.map +1 -1
  71. package/package.json +8 -5
package/README.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Anonymize code before it reaches an LLM, restore it after — from a terminal, a pipe, or a pre-commit hook.
4
4
 
5
+ > **Veilio is a set: install the guard, the CLI and the MCP server together.** Each does one job, and all three share one map (`.veilio/map.json`).
6
+ >
7
+ > - **[veilio-guard](../../plugins/veilio-guard/README.md)** keeps your names from the model while a coding agent works: it masks everything the agent reads - files, command output, search results and your prompts. Claude Code today; other agents are in progress.
8
+ > - **The CLI (this package)** does what the guard cannot, because the guard makes no network call: `veilio scrub` builds the map before the first session, `veilio maps pull` brings in your team's map and its numbers, `veilio rules pull` your custom rules, `veilio restore` brings back the names in an answer, and `veilio scan` stops a live key in a commit or in CI.
9
+ > - **[The MCP server](../mcp/README.md) (`@veilio-inc/mcp`)** gives the agent tools of its own: read a file masked, restore an answer, scan for secrets. In an agent the guard does not cover yet, it is the way in - with the agent's own file and shell tools turned off.
10
+ >
11
+ > **Without the guard, the CLI and the MCP server protect only what passes through them.** An agent that reads files and test output with its own tools sends them to the model as written: in our benchmark (spec 067, run 3), project names reached the model in 93-95 of 96 sessions with the MCP server or the CLI alone, and in 0 of 96 with the guard.
12
+
5
13
  ```bash
6
14
  veilio scrub src/billing.ts | pbcopy # mask, then paste anywhere
7
15
  pbpaste | veilio restore # bring the answer back
@@ -30,7 +38,7 @@ signed-in `scrub` offline, `veilio logout` first.
30
38
  | Command | Purpose |
31
39
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32
40
  | `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. |
41
+ | `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
42
  | `scan [files...]` | Detect credentials only. Never rewrites. Exits 1 on a credential; with `--strict`, on any finding. |
35
43
  | `map` | Show the symbol map (`--clear` to wipe it). |
36
44
 
@@ -49,9 +57,9 @@ veilio maps rm <id> # remove a map from Cloud
49
57
  veilio projects # the projects your team works in; * marks the one in use
50
58
  veilio projects use <name> # work in that project (kept with the sign-in)
51
59
  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
60
+ veilio team lock # remove the unlocked team key, and the team rules, from this machine
53
61
  veilio vault unlock # keep the personal-maps key here (7 days), for the MCP server
54
- veilio vault lock # remove it from this machine
62
+ veilio vault lock # remove it, and the personal rules, from this machine
55
63
  veilio rules pull # fetch your custom rules; scrub then applies them offline
56
64
  veilio logout # revokes server-side, then removes the local credential
57
65
  ```
@@ -119,6 +127,54 @@ Custom rules (whitelist and replace, set in the web app) are applied by
119
127
  offline - and says on every run how many rules it applied and how old the copy
120
128
  is. Pull again after the rules change; `logout` removes the copy.
121
129
 
130
+ Cloud holds the rules sealed under your keys, so it cannot read them: personal
131
+ rules under your personal-maps key, team rules under your team key. `rules pull`
132
+ opens them on this machine, so it needs `veilio vault unlock` for personal rules
133
+ and `veilio team unlock` for team rules. A rule it cannot open is skipped, never
134
+ an error: `scrub` still masks, with the built-in engine and the rules that did
135
+ open, and both commands say what was skipped and how to fix it, one sentence per
136
+ cause (on every `scrub`, `--quiet` included).
137
+
138
+ The opened rules last only as long as the key they were opened with.
139
+ `veilio vault lock` removes the personal rules from `rules.json`, and
140
+ `veilio team lock` the team rules, until the next unlock and `rules pull`; both
141
+ say how many they removed, and the copy counts them as vault locked or team key
142
+ locked. A key that expires, or is deleted by hand, has the same effect without
143
+ a lock: `scrub` and the MCP server apply a cached rule only while its key is
144
+ still on this machine, unexpired and for this account. A `rules pull` while
145
+ locked does not bring them back:
146
+
147
+ ```
148
+ 2 custom rules not applied: vault locked - run `veilio vault unlock`, then `veilio rules pull`.
149
+ 1 custom rule not applied: team key locked - run `veilio team unlock`, then `veilio rules pull`.
150
+ 1 custom rule not applied: could not be opened with the keys on this machine, and skipped.
151
+ 1 custom rule not applied: refused as unsafe to apply (an engine placeholder or a pattern rules do not support), and skipped.
152
+ ```
153
+
154
+ When some rules applied and others did not, `scrub` says both in one line:
155
+
156
+ ```
157
+ veilio: applied 1 custom rule pulled just now; 2 not applied: vault locked - run `veilio vault unlock`, then `veilio rules pull`.
158
+ ```
159
+
160
+ Under `--quiet` it prints only what was not applied, in the sentences above.
161
+
162
+ "Could not be opened" is a rule sealed under a team-key version this machine
163
+ does not hold (run `veilio team unlock` again after a rotation) or a damaged
164
+ one. "Refused" is a rule no tool applies, whoever wrote it: a replace
165
+ placeholder that reuses an engine base such as `__FN__`, a pattern the rule
166
+ matcher does not support (a backreference, lookaround, `\b`, or a bound over
167
+ 50), or a sealed body moved to another rule's row.
168
+
169
+ One `scrub` of one input spends a bounded amount of matching work on custom
170
+ rules, all rules and names together. Rules that would take more stop matching
171
+ part-way - the names after that point are masked as usual, none kept readable
172
+ or given a rule's placeholder - and `scrub` says so, under `--quiet` too:
173
+
174
+ ```
175
+ 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.
176
+ ```
177
+
122
178
  Four files, all `0600`, all under `~/.veilio/`: `credential.json` (the session
123
179
  and the chosen project, removed by `logout`), `rules.json` (the rules copy),
124
180
  `team-keys.json` (the keys `team unlock` opened, kept seven days) and
@@ -129,17 +185,90 @@ removes all of them.
129
185
 
130
186
  Signed in to a team with the team key unlocked, `veilio scrub` numbers from the
131
187
  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`.
188
+ gets the team's placeholder, and a new name is numbered inside this checkout's
189
+ block of team numbers (`.veilio/reserved.json`, below) - or, with no usable
190
+ block, in this checkout's local family `__LOCAL_<TAG>_<KIND>__n` - so it can
191
+ never take a number that means something else to a teammate. It is never
192
+ numbered above the team's highest: that is where the next teammate's block
193
+ starts. Only the team entries the output uses are kept in this project's map.
194
+ The summary says `Namespace: team`. `scrub` only reads `reserved.json`; it never
195
+ reserves, except with `--team`.
136
196
 
137
197
  - **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.
198
+ so on stderr, with the reason, even under `--quiet`. It is still a team, so
199
+ new names go into the local family (`__LOCAL_<TAG>_…`), never above the
200
+ map. The team comes from the team unlock, else from `~/.veilio/team.json`
201
+ (the team this account was last seen in, written by any command that lists
202
+ it and removed by `veilio logout`); with no `reserved.json` yet, scrub writes
203
+ one holding a fresh tag. With no team ever seen, new names still go into a
204
+ local family, under a tag for that run only.
140
205
  - **Signed out, it makes no request**, exactly as before. Signed in, it waits at
141
206
  most **5 seconds** for Cloud.
142
207
 
208
+ ### Team numbers for the guard
209
+
210
+ The Claude Code guard makes no request, so it cannot ask the team for a number
211
+ each time it masks a new name. Instead, `veilio maps pull` of a team map (and
212
+ `veilio team unlock` in a project that already has a map) reserves a **block**
213
+ of the team's numbers for you - 500 per kind - and keeps it in
214
+ `.veilio/reserved.json`. The guard numbers new names inside it, so two members
215
+ working at the same time never give one placeholder two meanings. A pull takes
216
+ a new block whenever a teammate's newer numbers sit above yours.
217
+
218
+ A reservation sends Cloud a kind, a count and a floor - never a name. The
219
+ engine's own kinds (`__VAR__`, `__FN__`, `__CLS__`, ...) go as they are; a
220
+ custom replace rule's placeholder (`__ACME_ACQUISITION_TARGET__`) names what
221
+ the team considers sensitive, so it is sent as `__H_<16 hex>__`, an HMAC of it
222
+ under the newest team key, and read back locally. Teammates holding the same
223
+ key send the same hash. Cloud counts each hash on its own, so a rule's kind is
224
+ floored above the team's reservations of it under its hash with every team key
225
+ version this machine holds (read from the team's reservations, which are only
226
+ ever asked for by hash): after a key rotation new numbers stay above the old
227
+ hash's while the old key is still held; without it, the floor is the map's.
228
+ Without the team key unlocked, or without that listing (an older instance),
229
+ numbers for a rule's kind are not reserved at all.
230
+
231
+ Only numbers Cloud issued count toward a floor. A number in a map that no run
232
+ of the team's reservations holds - one numbered on this machine, or planted -
233
+ is checked against the team's listing of its kind (`?bases=`, with each kind's
234
+ highest number) and floors nothing; for a kind never reserved yet, a map's
235
+ numbers floor its first run up to 10000. A pull says how many such numbers the
236
+ map held, and restore leaves one above the highest number Cloud has issued for
237
+ its kind. (A map from before team numbering with numbers above 10000, in a kind
238
+ never reserved, therefore floors nothing; such teams existed only on staging.)
239
+ Every reservation asks for an answer per kind: a kind Cloud refuses is numbered
240
+ on this machine (`__LOCAL_…`), with the refusal shown, and the others are
241
+ reserved. An older Cloud that refuses the whole call names the kinds it
242
+ refuses, and is asked again without them.
243
+
244
+ If no block can be reserved - the day's limit, offline, the plan, a server
245
+ error - the pull (or the unlock) still succeeds, exits 0, and says so on its
246
+ normal output, with the reason and, for the day's limit, when the next block is
247
+ possible:
248
+
249
+ ```
250
+ 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.
251
+ ```
252
+
253
+ `reserved.json` is still written, with the reason, and a signed-in
254
+ `veilio scrub` repeats the sentence on stderr - even under `--quiet` - for as
255
+ long as it holds. Until a block is held, the guard, a signed-in
256
+ `veilio scrub` and the MCP server number new names in this checkout's **local
257
+ family**, `__LOCAL_<TAG>_<KIND>__n` (`__LOCAL_K7Q2XA_VAR__3`). The tag is six
258
+ characters drawn for this checkout, so two checkouts never mint the same
259
+ string:
260
+
261
+ - **This machine restores them**, from its map.
262
+ - **A teammate's restore leaves them as written** and names them: only the
263
+ checkout that numbered one knows what it means.
264
+ - **The next team publish renumbers them** into reserved team numbers, keeps
265
+ the old placeholders in `.veilio/aliases.json` (they still restore here),
266
+ and draws a new tag.
267
+ - **No team map ever holds one.** A team map is sealed on your machine, so the
268
+ check is here too: a publish that would still seal one is refused, naming
269
+ them, and a reader drops one it finds - `maps pull` of a team map leaves
270
+ them out of `map.json` and says how many.
271
+
143
272
  ### Restoring a teammate's placeholders
144
273
 
145
274
  `veilio restore` resolves a placeholder this project's map cannot explain
@@ -151,6 +280,11 @@ with the real names:
151
280
  wins and the placeholder stays in the output with a line naming it. Same for
152
281
  one this project numbered on its own while the team was out of reach — a
153
282
  wrong name restored silently is worse than a placeholder left visibly.
283
+ - **Another checkout's local placeholder is left.** `__LOCAL_<TAG>_…` was
284
+ numbered on a checkout that held no team numbers; only that checkout restores
285
+ it, so it stays in the output, is named, and counts as left for `--strict`.
286
+ Your own restore still reads it, through `.veilio/aliases.json` once a publish
287
+ renumbered it.
154
288
  - **Locked, and it says so.** With no team key on this machine it tells you to
155
289
  run `veilio team unlock` rather than restoring half the text.
156
290
  - **Signed out, it makes no request at all** — that restore is as offline as it
@@ -176,11 +310,12 @@ a plan feature the web app couldn't.
176
310
  For: scrub
177
311
  -m, --map <path> Use a specific map file
178
312
  For: scrub, restore, map, maps pull, maps push, maps
179
- update
313
+ update, team unlock
180
314
  --json Machine-readable output
181
315
  For: scan, map
182
316
  --strict scan: also fail on advisory findings. restore: write
183
- nothing and exit 1 if a placeholder would be left
317
+ nothing and exit 1 if a placeholder or a redaction
318
+ would be left
184
319
  For: scan, restore
185
320
  --keep-docs Keep JSDoc blocks the model wrote
186
321
  For: restore
@@ -222,8 +357,9 @@ command.
222
357
  placeholder would be left in it — one the AI invented, one whose shape it changed
223
358
  (`__fn__1`), one the team's maps disagree on, or one the team's maps could not be
224
359
  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.
360
+ text, placeholders and all, names each one on stderr and exits 0. A value
361
+ redacted one-way (`__REDACTED_CREDENTIAL_1__`) cannot be restored, so the text is
362
+ not the original file: restore names it every time, and `--strict` refuses it.
227
363
 
228
364
  `--keep-docs` is worth knowing about: the default strip removes JSDoc along with
229
365
  the narration and TODOs, which is wrong when the model was _asked_ to document
@@ -254,12 +390,22 @@ files as arguments (`veilio scrub file`, `veilio restore answer.txt`) avoids
254
390
  the first problem; the line above avoids both. In 5.1, `>` also writes UTF-16,
255
391
  so write files from PowerShell 7 (`pwsh`).
256
392
 
393
+ ## When Veilio says the guard is missing
394
+
395
+ Run inside Claude Code (Claude Code sets `CLAUDECODE` for the commands it runs) on a machine where veilio-guard is not installed, every command prints one line to stderr:
396
+
397
+ ```text
398
+ veilio: veilio-guard is not installed. In Claude Code the CLI and MCP mask only what passes through them; the agent's own reads reach the model as written. Install it: /plugin install veilio-guard@veilio
399
+ ```
400
+
401
+ Standard output and the exit code are never changed, so pipes keep working. The line goes away once the guard is installed (the CLI reads Claude Code's plugin list, `~/.claude/plugins/installed_plugins.json`, and nothing else), and never shows under `--quiet`, with `CI` set, or outside Claude Code. A guard enforced only through your organisation's managed settings may not appear in that list; use `--quiet` there.
402
+
257
403
  ## Exit codes
258
404
 
259
405
  | Code | Meaning |
260
406
  | ---- | ------------------------------------------------------------------------------------------------------------------ |
261
407
  | 0 | Clean |
262
- | 1 | Findings that should stop the pipeline: a credential (`scan`), or a placeholder `restore --strict` would have left |
408
+ | 1 | Findings that should stop the pipeline: a credential (`scan`), or a placeholder or redaction `restore --strict` would have left |
263
409
  | 2 | Usage or IO error |
264
410
 
265
411
  As a pre-commit hook:
@@ -272,6 +418,21 @@ git diff --cached | veilio scan || {
272
418
  }
273
419
  ```
274
420
 
421
+ ## What is masked
422
+
423
+ Distinctive names - `quaywardThrottle`, `SkerryTariff`, `berth_quorum`, an invented
424
+ `tarnwick` - become placeholders. A name that is a single common English word
425
+ (`total`, `ledger`, `invoice`), shared vocabulary every codebase has (`src`,
426
+ `util`, `com`, `java`) or a toolchain's name (`vitest`, `junit`, `mvn`) is left as
427
+ written as a name or a path segment: it is nobody's secret, and masking it made
428
+ paths and test output unreadable. A codename that is an ordinary word (`phoenix`)
429
+ is therefore readable as a name; a custom replace rule (`veilio rules pull`) keeps
430
+ it masked. In a value - a string literal, a config value, XML text - every word is
431
+ masked. A value whose key contains a credential word (`password: sunshine`,
432
+ `DB_PASSWORD_PROD="sunshine"`, `const DB_PASS = "Summer2024!"`) is redacted one-way,
433
+ whole, under the default `--secrets redact`, so the map never holds it. Credentials
434
+ are redacted whatever they are called.
435
+
275
436
  ## The symbol map
276
437
 
277
438
  `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":"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"}