provared 0.1.0 → 0.3.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.
@@ -19,6 +19,7 @@
19
19
  // It reads one file and writes to the terminal. It makes no network request.
20
20
 
21
21
  import { readFileSync } from 'node:fs';
22
+ import { fileURLToPath } from 'node:url';
22
23
  import { MIN_BLOCKS_AFTER, REFUSAL_REASONS, blocksInChain, checkBook, checkHeaderChain, checkShow, conditionWords, limitWords, neverWords } from '../src/check.js';
23
24
 
24
25
  // Node.js marks its ML-DSA and SLH-DSA as experimental and says so on every
@@ -31,8 +32,11 @@ process.on('warning', (w) => {
31
32
  const USAGE = `Usage: provared-check <file> [--issuer <thumbprint>]... [--sealer <fingerprint>]... [--stamp-service <fingerprint>]...
32
33
  [--block <fingerprint>]... [--voucher <fingerprint>]... [--disclosures <file>] [--cancellation <file>]...
33
34
  [--root <top fingerprint>] [--size <entries>] [--headers <file>] [--json]
35
+ provared-check --sample [--json]
34
36
 
35
37
  <file> a book (one entry to a line) or a Show (one JSON object)
38
+ --sample check the sample record that comes with the library, naming the passkey, the recorder and the
39
+ time-stamp service it was made with as trusted (they are stand-ins, and the people are invented)
36
40
  --issuer the thumbprint of an issuer key you already trust; may be repeated
37
41
  --sealer the fingerprint of the key set of a recorder you expect to have sealed the book; may be repeated
38
42
  --stamp-service the fingerprint of the certificate of a time-stamp service you trust; may be repeated
@@ -64,13 +68,16 @@ const ONCE = { '--disclosures': 'disclosures', '--root': 'expectedRoot', '--size
64
68
  // fingerprint is refused, never set aside: a typing error must not quietly
65
69
  // leave a time-stamp or a name uncounted.
66
70
  function parseArguments(argv) {
67
- const out = { file: null, issuerKeys: [], sealKeys: [], stampServices: [], blocks: [], vouchers: [], cancellations: [], disclosures: undefined, expectedRoot: undefined, expectedSize: undefined, json: false };
71
+ const out = { file: null, sample: false, issuerKeys: [], sealKeys: [], stampServices: [], blocks: [], vouchers: [], cancellations: [], disclosures: undefined, expectedRoot: undefined, expectedSize: undefined, json: false };
68
72
  for (let i = 0; i < argv.length; i++) {
69
73
  const a = argv[i];
70
74
  if (a === '--help' || a === '-h') return { help: true };
71
75
  if (a === '--json') {
72
76
  if (out.json) return { error: '--json may be given once.' };
73
77
  out.json = true;
78
+ } else if (a === '--sample') {
79
+ if (out.sample) return { error: '--sample may be given once.' };
80
+ out.sample = true;
74
81
  } else if (Object.hasOwn(LISTS, a) || Object.hasOwn(ONCE, a)) {
75
82
  if (i + 1 >= argv.length) return { error: `${a} needs a value.` };
76
83
  const value = argv[++i];
@@ -85,6 +92,28 @@ function parseArguments(argv) {
85
92
  } else if (!a.startsWith('-') && out.file === null) out.file = a;
86
93
  else return { error: `${a.startsWith('-') ? 'Unknown option' : 'More than one file'}: ${safe(a)}` };
87
94
  }
95
+ if (out.sample) {
96
+ if (out.file !== null) return { error: '--sample names the sample record itself: give no file with it.' };
97
+ for (const name of ['issuerKeys', 'sealKeys', 'stampServices', 'blocks', 'vouchers', 'cancellations']) {
98
+ if (out[name].length) return { error: '--sample names what to trust itself: give no other option with it but --json.' };
99
+ }
100
+ if (out.disclosures !== undefined || out.expectedRoot !== undefined || out.expectedSize !== undefined || out.headers !== undefined) {
101
+ return { error: '--sample names what to trust itself: give no other option with it but --json.' };
102
+ }
103
+ // The sample, and the fingerprints of the stand-ins it was made with,
104
+ // come with the library (samples/office-supplies.expected.json).
105
+ let expected;
106
+ try {
107
+ expected = JSON.parse(readFileSync(new URL('../samples/office-supplies.expected.json', import.meta.url), 'utf8'));
108
+ } catch {
109
+ return { error: 'The sample record that comes with the library could not be read.' };
110
+ }
111
+ out.file = fileURLToPath(new URL('../samples/office-supplies.jsonl', import.meta.url));
112
+ out.issuerKeys = [expected.issuerKey];
113
+ out.sealKeys = [...expected.sealKeys];
114
+ out.stampServices = [...expected.stampServices];
115
+ return out;
116
+ }
88
117
  return out.file === null ? { error: 'No file was named.' } : out;
89
118
  }
90
119
 
@@ -469,6 +498,12 @@ if (args.error) {
469
498
  process.exit(2);
470
499
  }
471
500
 
501
+ if (args.sample && !args.json) {
502
+ console.log('The sample record that comes with the library: an invented office agent, under a permission signed with a stand-in for a passkey.');
503
+ console.log('Trusted for this check, as the sample was made with them: the stand-in passkey, the recorder and the time-stamp service.');
504
+ console.log(` --issuer ${args.issuerKeys[0]} --sealer ${args.sealKeys[0]} --stamp-service ${args.stampServices[0]}\n`);
505
+ }
506
+
472
507
  let text;
473
508
  try {
474
509
  text = readFileSync(args.file, 'utf8');