attenu-guard 0.11.0 → 0.13.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 (59) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +27 -0
  3. package/dist/cjs/audit.d.ts.map +1 -1
  4. package/dist/cjs/audit.js +45 -11
  5. package/dist/cjs/audit.js.map +1 -1
  6. package/dist/cjs/authority.d.ts.map +1 -1
  7. package/dist/cjs/authority.js +15 -9
  8. package/dist/cjs/authority.js.map +1 -1
  9. package/dist/cjs/canonical.d.ts +24 -0
  10. package/dist/cjs/canonical.d.ts.map +1 -1
  11. package/dist/cjs/canonical.js +49 -0
  12. package/dist/cjs/canonical.js.map +1 -1
  13. package/dist/cjs/ceilings.d.ts +17 -0
  14. package/dist/cjs/ceilings.d.ts.map +1 -1
  15. package/dist/cjs/ceilings.js +48 -0
  16. package/dist/cjs/ceilings.js.map +1 -1
  17. package/dist/cjs/cli.d.ts +16 -4
  18. package/dist/cjs/cli.d.ts.map +1 -1
  19. package/dist/cjs/cli.js +284 -21
  20. package/dist/cjs/cli.js.map +1 -1
  21. package/dist/cjs/display.d.ts +76 -0
  22. package/dist/cjs/display.d.ts.map +1 -0
  23. package/dist/cjs/display.js +238 -0
  24. package/dist/cjs/display.js.map +1 -0
  25. package/dist/cjs/evidence.d.ts +74 -5
  26. package/dist/cjs/evidence.d.ts.map +1 -1
  27. package/dist/cjs/evidence.js +655 -243
  28. package/dist/cjs/evidence.js.map +1 -1
  29. package/dist/cjs/version.d.ts +1 -1
  30. package/dist/cjs/version.js +1 -1
  31. package/dist/esm/audit.d.ts.map +1 -1
  32. package/dist/esm/audit.js +46 -12
  33. package/dist/esm/audit.js.map +1 -1
  34. package/dist/esm/authority.d.ts.map +1 -1
  35. package/dist/esm/authority.js +15 -9
  36. package/dist/esm/authority.js.map +1 -1
  37. package/dist/esm/canonical.d.ts +24 -0
  38. package/dist/esm/canonical.d.ts.map +1 -1
  39. package/dist/esm/canonical.js +46 -0
  40. package/dist/esm/canonical.js.map +1 -1
  41. package/dist/esm/ceilings.d.ts +17 -0
  42. package/dist/esm/ceilings.d.ts.map +1 -1
  43. package/dist/esm/ceilings.js +46 -0
  44. package/dist/esm/ceilings.js.map +1 -1
  45. package/dist/esm/cli.d.ts +16 -4
  46. package/dist/esm/cli.d.ts.map +1 -1
  47. package/dist/esm/cli.js +285 -22
  48. package/dist/esm/cli.js.map +1 -1
  49. package/dist/esm/display.d.ts +76 -0
  50. package/dist/esm/display.d.ts.map +1 -0
  51. package/dist/esm/display.js +226 -0
  52. package/dist/esm/display.js.map +1 -0
  53. package/dist/esm/evidence.d.ts +74 -5
  54. package/dist/esm/evidence.d.ts.map +1 -1
  55. package/dist/esm/evidence.js +638 -229
  56. package/dist/esm/evidence.js.map +1 -1
  57. package/dist/esm/version.d.ts +1 -1
  58. package/dist/esm/version.js +1 -1
  59. package/package.json +1 -1
package/dist/esm/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * attenu-guard — command-line tool.
3
3
  *
4
4
  * attenu-guard verify <log.jsonl | bundle.json> [--hs256-key HEX | --pubkey HEX] [--kid KID]
5
- * [--witness-keys FILE]
5
+ * [--witness-keys FILE] [--entries]
6
6
  *
7
7
  * A `.jsonl` audit log is checked for hash-chain integrity. A bundle (the
8
8
  * output of `exportBundle`, or of the Python library's `export_bundle`) is
@@ -10,53 +10,252 @@
10
10
  * bundle alone; the signed anchor is verified when a key is given and reported
11
11
  * as "not checked" otherwise. `--witness-keys FILE` supplies the trusted witness
12
12
  * keys for a bundle carrying observer envelopes; without it every envelope fails
13
- * `envelope_unknown_witness`, and the output says which flag to pass.
13
+ * `envelope_unknown_witness`, and the output says which flag to pass. A trust-set row may carry
14
+ * `not_after`; a row expired at the time of the run is not trusted. A trust file that is not one
15
+ * (not JSON, not an array of rows, or a row the verifier refuses) is one line naming the file and,
16
+ * for a bad row, the kid.
14
17
  *
15
- * Exit codes: 0 = ok, 2 = a check failed, 1 = usage. The output lines match the
16
- * Python CLI's, so either implementation can stand in for the other in a script.
18
+ * `--entries` prints, after everything else, `entries:` and one line per ledger entry: its seq,
19
+ * event, node and scope; on a bundle, its envelope state, with the observed result and the
20
+ * witness's kid when that state is witness-signed; and the checks that failed on that entry.
21
+ * Without the flag the output is unchanged.
22
+ *
23
+ * A ledger with zero events is reported EMPTY, not OK.
24
+ *
25
+ * Exit codes: 0 = ok, 2 = a check failed, there was nothing to check, or the trust file is
26
+ * malformed, 1 = usage (a missing argument, or a file that cannot be read).
27
+ * The output lines match the Python CLI's, so either implementation can stand in
28
+ * for the other in a script.
17
29
  */
18
30
  import { readFileSync } from "node:fs";
19
31
  import { AuditLog } from "./audit.js";
20
- import { parseBundle, verifyBundle } from "./evidence.js";
32
+ import { intOr, parseJson } from "./canonical.js";
33
+ import { BARE, escaped, integerText, oneLine } from "./display.js";
34
+ import { PROCESS_ASSERTED, WITNESS_SIGNED, integrityBreak, parseBundle, stateKey, validateWitnessKeys, verifyBundle, } from "./evidence.js";
21
35
  import { Ed25519Verifier, HS256TestSigner } from "./wire.js";
36
+ /** The Python CLI prints the same line for the same file. */
37
+ const EMPTY = "EMPTY — no events to verify";
22
38
  const USAGE = `attenu-guard — command-line tool.
23
39
 
24
40
  attenu-guard verify <log.jsonl | bundle.json> [--hs256-key HEX | --pubkey HEX] [--kid KID]
25
- [--witness-keys FILE]
41
+ [--witness-keys FILE] [--entries]
26
42
  verify a hash-chained audit log, or an evidence bundle
27
43
  (integrity · child ⊆ parent · containment;
28
44
  --hs256-key/--pubkey checks the anchor;
29
- --witness-keys FILE supplies the trusted observer-envelope keys)
45
+ --witness-keys FILE supplies the trusted observer-envelope keys;
46
+ --entries adds one line per entry: its envelope state and the checks that failed on it;
47
+ a line is key=value tokens split by single spaces, the key before the first "=",
48
+ and a value never contains a space; one that starts with " is a JSON string)
30
49
  `;
50
+ /** A `--witness-keys` file that was read and is not a trust set. The message says why. */
51
+ class NotATrustSet extends Error {
52
+ }
31
53
  /**
32
54
  * The trust set for a bundle's observer envelopes, read from `--witness-keys FILE`.
33
55
  *
34
56
  * The file is the `witness_keys` array the interop vectors carry — `[{kid, alg,
35
- * public_key_hex}]` — or one whole vector case, in which case its `witness_keys` member is used.
36
- * Without a trust set every envelope in a bundle fails `envelope_unknown_witness`, which is
37
- * correct (an unknown key is not a trusted one) and useless as a default, so this is how a bundle
38
- * carrying envelopes is verified from the command line.
57
+ * public_key_hex}]`, each row optionally with `not_after` — or one whole vector case, in which case
58
+ * its `witness_keys` member is used. Without a trust set every envelope in a bundle fails
59
+ * `envelope_unknown_witness`, which is correct (an unknown key is not a trusted one) and useless as
60
+ * a default, so this is how a bundle carrying envelopes is verified from the command line.
61
+ *
62
+ * Every row is validated here, by the same checks the verifier runs, so a bad row is reported
63
+ * against this file before any bundle is read. Throws the file system's error when the file cannot
64
+ * be read, and `NotATrustSet` when it is not a trust set: not JSON (JSON is UTF-8 text, so bytes
65
+ * that are not UTF-8 are not JSON either), not an array of rows, or a row the verifier refuses,
66
+ * whose message names the kid. The messages are the Python CLI's, word for word.
39
67
  */
40
68
  function readWitnessKeys(path) {
41
- let parsed = JSON.parse(readFileSync(path, "utf8"));
69
+ const bytes = readFileSync(path);
70
+ let parsed;
71
+ try {
72
+ // `ignoreBOM` keeps a byte-order mark in the text, where JSON.parse refuses it as Python does.
73
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes));
74
+ }
75
+ catch {
76
+ throw new NotATrustSet("the file is not valid JSON");
77
+ }
42
78
  if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && "witness_keys" in parsed) {
43
79
  parsed = parsed["witness_keys"];
44
80
  }
45
81
  if (!Array.isArray(parsed)) {
46
- throw new Error(`${path}: expected a list of {kid, alg, public_key_hex}, got ${typeof parsed}`);
82
+ throw new NotATrustSet("expected a JSON array of {kid, alg, public_key_hex} rows, or a vector case carrying one as witness_keys");
83
+ }
84
+ try {
85
+ validateWitnessKeys(parsed);
86
+ }
87
+ catch (err) {
88
+ throw new NotATrustSet(err.message);
47
89
  }
48
90
  return parsed;
49
91
  }
92
+ /**
93
+ * The C library's text for the file-system errors a path argument meets — what Python prints as
94
+ * `strerror` — so `cannot read FILE: REASON` reads the same from both CLIs. `null` for an error
95
+ * that is not a file-system one. A code outside this table prints Node's own message, which is
96
+ * worded differently.
97
+ */
98
+ function readFailure(err) {
99
+ const code = err?.code;
100
+ if (typeof code !== "string")
101
+ return null;
102
+ return STRERROR[code] ?? err.message;
103
+ }
104
+ const STRERROR = {
105
+ ENOENT: "No such file or directory",
106
+ EACCES: "Permission denied",
107
+ EISDIR: "Is a directory",
108
+ ENOTDIR: "Not a directory",
109
+ ELOOP: "Too many levels of symbolic links",
110
+ ENAMETOOLONG: "File name too long",
111
+ EPERM: "Operation not permitted",
112
+ EMFILE: "Too many open files",
113
+ EINVAL: "Invalid argument",
114
+ EIO: "Input/output error",
115
+ };
50
116
  /** Render a boolean the way Python does, so the two CLIs print the same line. */
51
117
  function py(value) {
52
118
  return value ? "True" : "False";
53
119
  }
120
+ /**
121
+ * Entry index -> the checks that failed on that entry: the `reason` of every failure about it,
122
+ * each once, in the order the verifier reported them.
123
+ *
124
+ * `failureEntries` is the verifier's own record of the entry each failure is about, by index
125
+ * (`VerifyReport.failure_entries`), so a failure lands on its entry even when that entry's seq is
126
+ * missing, null, a boolean, a string or another entry's. A failure about no single entry (a
127
+ * version, root, anchor or chain-id failure, or an envelope whose subject names no entry) is in
128
+ * the bundle-level output already and lands on no line.
129
+ */
130
+ function failedByEntry(failureEntries, details) {
131
+ const failed = new Map();
132
+ failureEntries.forEach((index, k) => {
133
+ if (index === null)
134
+ return;
135
+ const reason = details[k].reason;
136
+ const reasons = failed.get(index) ?? [];
137
+ if (!reasons.includes(reason))
138
+ reasons.push(reason);
139
+ failed.set(index, reasons);
140
+ });
141
+ return failed;
142
+ }
143
+ /**
144
+ * One value on an `--entries` line, byte for byte what the Python CLI prints.
145
+ *
146
+ * The values come from the bundle, which is attacker-supplied, and a line is only worth reading if
147
+ * no value can end it early or start a forged one: a `scope` carrying a newline and a clean-looking
148
+ * second line would otherwise print a fake entry with the real entry's `failed=` attached to it. So
149
+ * a value is printed as it is only when it is printable ASCII with no space, `"` or `\`, and an
150
+ * integer in decimal. Anything else is printed in the `escaped` JSON form (display.ts), which holds
151
+ * no whitespace and which a JSON parser reads back.
152
+ */
153
+ function entryValue(value) {
154
+ if (typeof value === "string" && BARE.test(value))
155
+ return value;
156
+ return integerText(value) ?? escaped(value);
157
+ }
158
+ /**
159
+ * One `--entries` line: two spaces, then `key=value` tokens separated by single spaces, in a fixed
160
+ * order. `seq` is always printed, as the integer when it is integral (`1.0` prints 1, as the
161
+ * verifier reads it), and as `seq=null` for an entry that has none: an entry without a seq is
162
+ * exactly the entry a reader must see. Any other key with no value is left out.
163
+ *
164
+ * How a line parses: no token contains whitespace; the key is the text before the token's first
165
+ * `=`, and keys never contain one, though a value may (`scope=failed=containment` is the scope
166
+ * "failed=containment"); a value that starts with `"` is a JSON string, and any other value is
167
+ * printed as it is.
168
+ */
169
+ function entryLine(e, rest) {
170
+ const tokens = [`seq=${entryValue((intOr(e["seq"]) ?? null))}`];
171
+ const pairs = [
172
+ ["event", e["event"]],
173
+ ["node", e["node"]],
174
+ ["scope", e["scope"]],
175
+ ...rest,
176
+ ];
177
+ for (const [key, value] of pairs) {
178
+ if (value !== null && value !== undefined)
179
+ tokens.push(`${key}=${entryValue(value)}`);
180
+ }
181
+ return ` ${tokens.join(" ")}`;
182
+ }
183
+ /**
184
+ * A bundle's entries with the state the verifier computed for each, read by index: an entry is
185
+ * witness-signed exactly when `envelopes.witnesses` holds its index, which is the entry the
186
+ * verifier resolved an envelope to, so of two entries sharing a seq only the one the witness signed
187
+ * reads witness-signed. `observed` and `witness` are printed only on such an entry: they are what
188
+ * its envelope says, and an entry that is process-asserted carries no observation the reader may
189
+ * rely on.
190
+ */
191
+ function bundleEntryLines(entries, rep) {
192
+ const failed = failedByEntry(rep.failure_entries, rep.failure_details);
193
+ const { results, witnesses } = rep.envelopes;
194
+ return entries.map((e, i) => {
195
+ const kid = Object.hasOwn(witnesses, String(i)) ? witnesses[String(i)] : null;
196
+ // `results` is keyed the way `states` is (`stateKey`), and for a covered entry the result filed
197
+ // there is its own envelope's.
198
+ const key = stateKey(e, i);
199
+ return entryLine(e, [
200
+ ["state", kid === null ? PROCESS_ASSERTED : WITNESS_SIGNED],
201
+ ["observed", kid !== null && Object.hasOwn(results, key) ? results[key] : null],
202
+ ["witness", kid],
203
+ ["failed", failed.get(i)?.join(",") ?? null],
204
+ ]);
205
+ });
206
+ }
207
+ /** A plain ledger's entries. A plain ledger carries no envelopes, so there is no state to print. */
208
+ function ledgerEntryLines(entries, failureEntries, details) {
209
+ const failed = failedByEntry(failureEntries, details);
210
+ return entries.map((e, i) => entryLine(e, [["failed", failed.get(i)?.join(",") ?? null]]));
211
+ }
212
+ /** One JSON object with an `entries` member: what `exportBundle` writes. */
213
+ function isBundleShaped(value) {
214
+ return value !== null && typeof value === "object" && !Array.isArray(value) && "entries" in value;
215
+ }
216
+ /**
217
+ * Why a file that is neither a bundle nor a ledger could not be read, in one line.
218
+ *
219
+ * A file that is ONE JSON object with `entries`, read by JavaScript's lenient parser, is a bundle
220
+ * the strict one refused — a duplicate member, a number past the double range, a lone surrogate —
221
+ * and that refusal is the reason. Anything else was read as JSON Lines, and the reason is the first
222
+ * line that does not parse. A parser's message can quote the input, so it goes through `oneLine`.
223
+ */
224
+ function unparsable(text, bundleError, ledgerError) {
225
+ if (bundleError !== null) {
226
+ let lenient = null;
227
+ try {
228
+ lenient = JSON.parse(text);
229
+ }
230
+ catch {
231
+ lenient = null;
232
+ }
233
+ if (isBundleShaped(lenient))
234
+ return oneLine(bundleError.message);
235
+ }
236
+ const lines = text.split(/\r?\n/);
237
+ for (let n = 0; n < lines.length; n++) {
238
+ if (lines[n].trim() === "")
239
+ continue;
240
+ try {
241
+ parseJson(lines[n]);
242
+ }
243
+ catch (err) {
244
+ return `line ${n + 1}: ${oneLine(err.message)}`;
245
+ }
246
+ }
247
+ return oneLine(ledgerError.message);
248
+ }
249
+ function writeEntries(lines) {
250
+ process.stdout.write(`entries:\n${lines.map((line) => `${line}\n`).join("")}`);
251
+ }
54
252
  function verify(args) {
55
253
  let path = null;
56
254
  let keyHex = null;
57
255
  let pubHex = null;
58
256
  let kid = null;
59
257
  let witnessPath = null;
258
+ let listEntries = false;
60
259
  for (let i = 0; i < args.length; i++) {
61
260
  const a = args[i];
62
261
  if (a === "--hs256-key")
@@ -67,6 +266,8 @@ function verify(args) {
67
266
  kid = args[++i] ?? null;
68
267
  else if (a === "--witness-keys")
69
268
  witnessPath = args[++i] ?? null;
269
+ else if (a === "--entries")
270
+ listEntries = true;
70
271
  else if (path === null)
71
272
  path = a;
72
273
  }
@@ -74,18 +275,28 @@ function verify(args) {
74
275
  process.stdout.write(USAGE);
75
276
  return 1;
76
277
  }
77
- const text = readFileSync(path, "utf8");
278
+ let text;
279
+ try {
280
+ text = readFileSync(path, "utf8");
281
+ }
282
+ catch (err) {
283
+ // A wrong path is a usage error, not a stack trace.
284
+ const reason = readFailure(err);
285
+ if (reason === null)
286
+ throw err;
287
+ process.stdout.write(`cannot read ${path}: ${reason}\n`);
288
+ return 1;
289
+ }
78
290
  let bundle = null;
291
+ let bundleError = null;
79
292
  try {
80
293
  // A bundle is ONE JSON object; a ledger is JSON Lines.
81
294
  const parsed = parseBundle(text);
82
- bundle =
83
- parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && "entries" in parsed
84
- ? parsed
85
- : null;
295
+ bundle = isBundleShaped(parsed) ? parsed : null;
86
296
  }
87
- catch {
297
+ catch (err) {
88
298
  bundle = null;
299
+ bundleError = err;
89
300
  }
90
301
  if (bundle !== null) {
91
302
  const anchorKid = bundle.anchor?.["kid"] ?? undefined;
@@ -95,12 +306,34 @@ function verify(args) {
95
306
  else if (pubHex) {
96
307
  signer = new Ed25519Verifier(Buffer.from(pubHex, "hex"), kid ?? anchorKid ?? "k1");
97
308
  }
98
- const witnessKeys = witnessPath === null ? null : readWitnessKeys(witnessPath);
309
+ let witnessKeys = null;
310
+ if (witnessPath) {
311
+ try {
312
+ witnessKeys = readWitnessKeys(witnessPath);
313
+ }
314
+ catch (err) {
315
+ // Read, and not a trust set: one line, naming the file and, for a bad row, the kid.
316
+ if (err instanceof NotATrustSet) {
317
+ process.stdout.write(`cannot use --witness-keys ${witnessPath}: ${err.message}\n`);
318
+ return 2;
319
+ }
320
+ // Unreadable, as for the bundle path above.
321
+ const reason = readFailure(err);
322
+ if (reason === null)
323
+ throw err;
324
+ process.stdout.write(`cannot read ${witnessPath}: ${reason}\n`);
325
+ return 1;
326
+ }
327
+ }
99
328
  const rep = verifyBundle(bundle, signer, { witnessKeys });
100
329
  const c = rep.checks;
330
+ // An allow marked `policy: "unlisted"` passed through un-gated and is excused from containment,
331
+ // so `actions_checked` does not count it. Say how many there were, only when there were any:
332
+ // every other bundle prints this line exactly as it always has.
333
+ const ungated = rep.ungated > 0 ? ` ungated=${rep.ungated}` : "";
101
334
  process.stdout.write(`integrity=${py(c.integrity)} monotonicity=${py(c.monotonicity)} ` +
102
335
  `containment=${py(c.containment)} anchor=${c.anchor} ` +
103
- `nodes=${rep.nodes} actions_checked=${rep.actions_checked}\n`);
336
+ `nodes=${rep.nodes} actions_checked=${rep.actions_checked}${ungated}\n`);
104
337
  for (const f of rep.failures)
105
338
  process.stdout.write(` - ${f}\n`);
106
339
  // A bundle carrying envelopes and no trust set fails every one of them, correctly and
@@ -110,11 +343,41 @@ function verify(args) {
110
343
  process.stdout.write("hint: pass --witness-keys FILE to supply the trusted witness keys\n");
111
344
  }
112
345
  process.stdout.write(rep.ok ? "OK\n" : "FAILED\n");
346
+ if (listEntries)
347
+ writeEntries(bundleEntryLines(bundle.entries ?? [], rep));
113
348
  return rep.ok ? 0 : 2;
114
349
  }
115
- const entries = AuditLog.parseLines(text);
350
+ let entries;
351
+ try {
352
+ entries = AuditLog.parseLines(text);
353
+ }
354
+ catch (err) {
355
+ // Neither a bundle nor a ledger this build reads: one line, not a stack trace. Exit 1, as the
356
+ // Python CLI exits on a file it cannot parse.
357
+ process.stdout.write(`cannot parse ${path}: ${unparsable(text, bundleError, err)}\n`);
358
+ return 1;
359
+ }
360
+ if (entries.length === 0) {
361
+ // A ledger with no entries has nothing to verify. Reporting it OK would be a fail-open: a
362
+ // truncated or never-written file would pass the same check as a clean chain.
363
+ process.stdout.write(`${EMPTY}\n`);
364
+ if (listEntries)
365
+ writeEntries([]);
366
+ return 2;
367
+ }
116
368
  const [ok, reason] = AuditLog.verify(entries);
117
369
  process.stdout.write(ok ? "OK\n" : `TAMPERED — ${reason}\n`);
370
+ if (listEntries) {
371
+ // A plain ledger has one check, the hash chain, and its failure is about the entry a bundle's
372
+ // integrity failure is about: the first one the chain does not reproduce at.
373
+ const at = [];
374
+ const details = [];
375
+ if (!ok) {
376
+ at.push(integrityBreak(entries));
377
+ details.push({ reason: "integrity", seq: null, node: null, call_id: null, detail: `integrity: ${reason}` });
378
+ }
379
+ writeEntries(ledgerEntryLines(entries, at, details));
380
+ }
118
381
  return ok ? 0 : 2;
119
382
  }
120
383
  export function main(argv = process.argv.slice(2)) {
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * display.ts — how a value from a ledger, a bundle or a trust file is printed into a line of text.
3
+ *
4
+ * A ledger, a bundle and the envelopes beside it are untrusted input, and their values reach a
5
+ * terminal through the verifier's finding messages, `attenu-guard verify`, and `--entries`. A value
6
+ * that carries a line break can end the line it is printed on and start a forged one: a node named
7
+ * "n1\nOK" would print a line reading `OK` under a failed verification. Two rules cover every place
8
+ * such a value is printed, and both are the Python implementation's, byte for byte:
9
+ *
10
+ * - a value printed bare goes through `shown`: as its text when that text is printable ASCII
11
+ * 0x21-0x7E other than `"` and `\`, so clean input prints exactly as it always has, and as its
12
+ * `escaped` JSON form otherwise, which holds no whitespace and no line break;
13
+ * - a value printed the way Python's `repr` prints it goes through `pyRepr`, which quotes and
14
+ * escapes a string exactly as `repr` does. Python's `{x!r}` needs no other rule, so neither
15
+ * does this.
16
+ */
17
+ import { type CJson } from "./canonical.js";
18
+ /** The bare form: printable ASCII 0x21-0x7E without `"` (0x22) or `\` (0x5C). */
19
+ export declare const BARE: RegExp;
20
+ /**
21
+ * Python's `repr` of a `str`: single quotes unless the text holds a `'` and no `"`, the quote and
22
+ * the backslash escaped, `\t` `\n` `\r` by name, any other control character or DEL as `\xHH`, and
23
+ * a non-ASCII character as it is when Python counts it printable, as `\xHH`, `\uHHHH` or
24
+ * `\UHHHHHHHH` when it does not. Lower-case hex throughout, as CPython writes it.
25
+ */
26
+ export declare function pyStrRepr(s: string): string;
27
+ /**
28
+ * `text` with every character Python's `repr` would escape written as that escape, and nothing
29
+ * else changed: no quotes added, no backslash doubled. For a parser's message, which can quote a
30
+ * fragment of the input it refused: one line, always.
31
+ */
32
+ export declare function oneLine(text: string): string;
33
+ /**
34
+ * Python-style `repr` for the value types a finding message carries. A number that kept its
35
+ * literal prints as Python prints what `json` reads from it (`1` an int, `1.0` a float); a number
36
+ * that has lost its literal prints as JavaScript prints it, as this module always has.
37
+ */
38
+ export declare function pyRepr(value: CJson): string;
39
+ /**
40
+ * Python's `str()` where a message interpolates a value bare (`{x}`) rather than through `repr`
41
+ * (`{x!r}`): the same rendering for every type except a string, which `str` leaves unquoted.
42
+ */
43
+ export declare function pyStr(value: CJson): string;
44
+ /**
45
+ * `value` as a finding message prints it bare: its text (Python's `str`) when that text is bare,
46
+ * its `escaped` JSON form otherwise. Clean values print exactly as they always have. An absent
47
+ * value is Python's `None`.
48
+ */
49
+ export declare function shown(value: CJson | undefined): string;
50
+ /**
51
+ * `shown`, for a caller that already holds the text Python's `str` gives for `value` (a ceiling
52
+ * renders its numbers the way Python renders a float): the text when it is bare, `value`'s
53
+ * `escaped` form otherwise.
54
+ */
55
+ export declare function shownText(text: string, value: CJson): string;
56
+ /**
57
+ * `value` as whitespace-free, ASCII-only JSON: Python's
58
+ * `json.dumps(value, ensure_ascii=True, separators=(",", ":"))`, with every space then written as
59
+ * `\u0020`. Inside a string that is `\"` and `\\`, the short escapes `\n` `\t` `\r` `\b` `\f`, and
60
+ * a lower-case `\uXXXX` for every other UTF-16 unit outside printable ASCII. That form holds no
61
+ * whitespace and no line break, and a JSON parser gives the value back.
62
+ */
63
+ export declare function escaped(value: CJson): string;
64
+ /**
65
+ * A number Python's `json` reads as an `int`, in decimal, or `null` for anything else. A parsed
66
+ * bundle keeps every number's literal, so `1` and `1.0` stay as distinct as they are in Python. A
67
+ * number that has lost its literal is read as an integer when it is integral.
68
+ */
69
+ export declare function integerText(value: CJson): string | null;
70
+ /**
71
+ * Python's `repr` of a float, which `json` writes: the shortest digits that read back as the same
72
+ * number, in positional form from 1e-4 up to below 1e16 with `.0` on an integral value, and in
73
+ * exponent form, with a two-digit exponent at least, outside that range.
74
+ */
75
+ export declare function pyFloat(n: number): string;
76
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/display.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvD,iFAAiF;AACjF,eAAO,MAAM,IAAI,QAAmB,CAAC;AAErC;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5C;AA0BD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAe3C;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAGtD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAMvD;AAuCD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBzC"}