provared 0.1.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 (49) hide show
  1. package/CHANGELOG.md +1062 -0
  2. package/LICENSE +202 -0
  3. package/LICENSE-CC-BY-4.0.txt +396 -0
  4. package/README.md +689 -0
  5. package/bin/provared-check.mjs +565 -0
  6. package/bin/provared-headers.mjs +110 -0
  7. package/docs/threat-model.md +997 -0
  8. package/net/headers.js +403 -0
  9. package/package.json +57 -0
  10. package/page/check-page.js +162 -0
  11. package/page/index.html +47 -0
  12. package/page/render.js +530 -0
  13. package/page/style.css +150 -0
  14. package/samples/office-supplies.expected.json +82 -0
  15. package/samples/office-supplies.jsonl +10 -0
  16. package/samples/office-supplies.show.json +59 -0
  17. package/spec/provared-format.md +1672 -0
  18. package/src/actions.js +90 -0
  19. package/src/approval.js +73 -0
  20. package/src/blockstamp.js +198 -0
  21. package/src/book.js +2232 -0
  22. package/src/check.d.ts +21 -0
  23. package/src/check.js +15 -0
  24. package/src/compare.js +276 -0
  25. package/src/cover.js +198 -0
  26. package/src/der.js +192 -0
  27. package/src/encoding.js +286 -0
  28. package/src/fields.js +94 -0
  29. package/src/guard.js +171 -0
  30. package/src/headers.js +380 -0
  31. package/src/index.d.ts +2 -0
  32. package/src/index.js +37 -0
  33. package/src/jws.js +235 -0
  34. package/src/keys.js +149 -0
  35. package/src/pass.js +67 -0
  36. package/src/passkey-browser.d.ts +20 -0
  37. package/src/passkey-browser.js +171 -0
  38. package/src/recorder.js +1115 -0
  39. package/src/seal.js +133 -0
  40. package/src/service.js +124 -0
  41. package/src/signatures.js +147 -0
  42. package/src/slip.js +401 -0
  43. package/src/standing.js +181 -0
  44. package/src/stub.js +140 -0
  45. package/src/timestamp.js +351 -0
  46. package/src/tools.js +192 -0
  47. package/src/tree.js +143 -0
  48. package/src/types.d.ts +628 -0
  49. package/src/webauthn.js +119 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,1062 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ Draft version 0 of the format. Nothing is published or frozen.
6
+
7
+ - 2026-10-05: `provared-headers` is marked as experimental, in the
8
+ README and in what the command prints.
9
+ - 2026-10-05: faults found by an independent review of the chain of
10
+ block headers. It found no way to have a block counted unless real
11
+ work made it: no chain file and no answer from a node did. Each fault
12
+ is fixed and each is now a test (`test/headers.test.mjs`).
13
+ - The second node did not have to show anything: an empty answer
14
+ counted as agreeing, a node behind could agree, and other nodes could
15
+ cut the end of the chain or swap it for a branch with no more work,
16
+ after which the file was written shorter. Now the second node is
17
+ asked for the latest six blocks on a copy of the chain and must hand
18
+ them back itself; it must be on a network apart from every node that
19
+ gave headers, judged by the address reached, not the name given; a
20
+ branch near the end is taken on only if it carries more work; and a
21
+ chain file is never written shorter than it was.
22
+ - A node could keep `provared-headers` waiting for ever with messages
23
+ of its own, and grow its memory with requests to answer. Now a node
24
+ is given fifteen minutes at most, only answers to what was asked keep
25
+ a session open, and answers to its own messages stop while it does
26
+ not read them.
27
+ - The list of threats said that a branch after the last known block
28
+ must carry the real chain's work for every block. The rules on
29
+ difficulty let a branch with dates pushed forward ease its targets at
30
+ each change. Now, after the last known block, no target may be more
31
+ than four times easier than that block's, and the list of threats
32
+ states what a false block then costs, and that a chain file someone
33
+ else hands over is only as good as they are.
34
+ - With `--headers`, the checker said that a block found in the chain
35
+ was one "you named as trusted", and that a block named with
36
+ `--block` was not counted. It now says why each block counts, and
37
+ `--json` gives what the chain showed beside the result.
38
+ - A file that could not be written ended the command with an error of
39
+ its own, and a run that fetched nothing wrote the first block alone.
40
+ Now both are said plainly, nothing is written, and a chain file is
41
+ made sure to be on the disk before it takes the old one's place.
42
+ - Also: the lowest header version after the upgrades of 2013 and 2015,
43
+ and a target of zero, are refused, as nodes refuse them; node
44
+ addresses are read strictly, and lines of a file of nodes that are
45
+ not addresses are counted and said.
46
+
47
+ - 2026-10-05: a block time-stamp can be checked with no node of your
48
+ own. A new command, `provared-headers`, fetches the chain of Bitcoin
49
+ block headers from nodes the person names, and from no one else, and
50
+ keeps it in a file; a second node on another network must hold the same
51
+ latest block. `provared-check --headers <file>` checks that file on the
52
+ device, from the chain's first block, by the rules every Bitcoin node
53
+ applies to headers, and against ten blocks known to be part of the
54
+ chain; a block time-stamp then counts if its block is in the chain with
55
+ at least six blocks after it. In the library: `checkHeaderChain` and
56
+ `blocksInChain`. The network code sits apart, in `net/`, and only the
57
+ new command uses it: the library and the checker still make no
58
+ request. New code: `headers-invalid`. Tried once against the real
59
+ network: the whole chain, 970,076 headers checked from the first
60
+ block, in about six minutes, the same headers as the test against real
61
+ proofs fetched; a second run fetched only what was new. Built from the
62
+ script of that test.
63
+
64
+ - 2026-10-05: faults found by a broad final review of the package as it
65
+ is to be published. It found nothing that made a changed record read
66
+ as intact, nothing that crashed the checker, and no request made by
67
+ the checking page built as one file. Each fault is fixed and each is
68
+ now a test (`test/review20.test.mjs`).
69
+ - **Exit code 0, and the checking page's green answer, now need the
70
+ keys you named:** the passkey you trust and, where the record has a
71
+ seal, the recorder you expect. Before, a stranger's record, or a book
72
+ cut short and sealed again with other recorder keys, gave code 0
73
+ with nothing trusted named. The command-line checker now says
74
+ whether the check rests on keys you named. The library's own answer
75
+ is unchanged.
76
+ - The command-line checker refuses a trust value that is not a
77
+ fingerprint (a typing error had left a time-stamp quietly not
78
+ counted), refuses an option given twice where it may be given once,
79
+ ends with code 0 for `--help`, and does not repeat Node.js's warning
80
+ that its ML-DSA and SLH-DSA are experimental.
81
+ - A run of more than three marks drawn on one letter (accents, for
82
+ one) is shown as three and one visible mark, on the page and in the
83
+ terminal, and each value on the page stays inside its own box. A
84
+ purpose of one letter and 999 such marks had been drawn over the
85
+ page's answer.
86
+ - Checking the sample on the page no longer leaves the sample's
87
+ fingerprints in the boxes, where they made the next record chosen
88
+ read as signed by a passkey not trusted.
89
+ - A stub whose slip fails is no longer counted as one-sided: its
90
+ countersignature, not checked, is `unchecked`.
91
+ - In a browser, a slip can now be cancelled with its passkey
92
+ (`cancelWithPasskey`), and anything prepared for a passkey, such as
93
+ a slip with covered fields, signed (`signChallengeWithPasskey`).
94
+ - A line that ends with a carriage return before its line feed, a
95
+ byte-order mark, or an empty line is now named as such. The codes
96
+ are unchanged.
97
+ - The README says how to install and import the package, and which
98
+ commands need a copy of the repository. Two of its claims went
99
+ further than the code: the check before acting refuses more than a
100
+ checker reports in one case, and a seal fixes what is before it only
101
+ for a recorder you named. Both now say so. `package.json` names both
102
+ licences and the repository. Out-of-date sentences in the list of
103
+ threats and the format description are corrected, and a time-stamp
104
+ shows that entries "existed by" a time, for both kinds.
105
+
106
+ - 2026-10-05: faults found by a nineteenth independent review, of the
107
+ eighteenth review's fixes. Each is fixed and each is now a test
108
+ (`test/review19.test.mjs`). In 3,900 random steps the review found
109
+ no action taken after the person's cancellation was handed over, no
110
+ difference between the stub writer's view of its book and a whole
111
+ check, and no line written that made the book fail its check.
112
+ - The entry below for the eighteenth review says that a value too
113
+ large to be a line of a book is refused before it is written out.
114
+ The limit counted values, not their length, and each member of an
115
+ entry by itself. So a long text met many times, or one long list
116
+ named by many members, could make `add` use gigabytes of memory, or
117
+ end the process, before the call waited its turn. The copy is now
118
+ measured by the length its text would have: each of the three
119
+ members of a cancellation has room for a line, and the other
120
+ members share one line's room. Past that, the entry is not written
121
+ as it was handed over, and the cancellation in it still stops the
122
+ writer. Anything but an object, such as a list, is no longer written
123
+ out, and one that cannot even be looked into is refused through the
124
+ answer, not thrown.
125
+ - A list whose length is not a whole number (a Proxy can say
126
+ anything) was copied as a list that held that value. A list of
127
+ trusted passkeys whose length was a passkey's thumbprint then
128
+ trusted that passkey, and in `add` a list of time-stamps whose
129
+ length was a time-stamp put it into the book. In the options such a
130
+ list is now kept as it was handed over; in `add` it is not plain
131
+ data.
132
+ - An option for the signing methods to treat as not built in that
133
+ could not be read made a whole check and a carried checker throw.
134
+ It is now a problem with the whole check (`check-failed`).
135
+ - A value more than 16 levels down in the options was kept as it was
136
+ handed over. Through a value met twice it could appear near the top
137
+ of a carried checker's options, so that a change made afterwards
138
+ changed its answer. Nothing past that depth is kept now: it cannot
139
+ be read.
140
+ - The stub writer copied the passkeys it trusts with the platform's
141
+ own copy, which refuses a list wrapped in a Proxy. They are now read
142
+ through the same fixed copy as the other options.
143
+ - The check before acting no longer copies its options twice, and a
144
+ gap at the end of a list in the options is now held by a test.
145
+
146
+ - 2026-10-05: the block time-stamp checked once against real proofs.
147
+ Two complete proofs that others had published, one made by hand and
148
+ one made by public calendar services, were read with this library's
149
+ reader against the headers of the real blocks they name: each led to
150
+ its blocks (five in all), and each was refused with another block's
151
+ header or with its file changed by one bit. The headers came from the
152
+ whole chain of headers, checked from its first block. The proofs and
153
+ their files are not copied into the repository, and the tests still
154
+ use made-up blocks. The README and the list of threats say so.
155
+
156
+ - 2026-10-05: faults found by an eighteenth independent review, of the
157
+ seventeenth review's fixes. Each is fixed and each is now a test
158
+ (`test/review18.test.mjs`). In 18,000 random steps the review found
159
+ no action taken after the person's cancellation was handed over, no
160
+ difference between the stub writer's view of its book and a whole
161
+ check, and no line written that made the book fail its check.
162
+ - Since the seventeenth review's fixes, a whole check, a Show and the
163
+ check before acting read their options through a fixed copy. Options
164
+ that shared values many times over, or that held themselves, then
165
+ took more than twenty seconds to copy, or used up the memory. A
166
+ value met twice is now copied once, so the copy costs no more than
167
+ the options hold.
168
+ - An option that cannot even be looked into (a revoked Proxy) made a
169
+ whole check, a carried checker and the stub writer throw an error of
170
+ the platform's own, where they should answer. It is now a problem
171
+ with the whole check (`check-failed`), and the stub writer refuses it
172
+ when it is opened (`bad-field`).
173
+ - What is handed to `add` was copied in two steps where it could not
174
+ be copied at once (a Proxy beside it), so a member could be read
175
+ twice, and a member that changed between the two readings could let
176
+ the writer act after the person's cancellation was handed over. It
177
+ is now copied in one pass, each member and each place read once. In
178
+ the same way, a sound time-stamp beside a gap or a faulty item, in a
179
+ list wrapped in a Proxy, is no longer lost. A value too large to be a
180
+ line of a book is refused before it is written out.
181
+ - An acknowledgement that waits, carried by a copy given at opening,
182
+ was the first to give way where more than sixteen were held. The
183
+ acknowledgements that wait now give way newest first.
184
+ - A copy of a cancellation given at opening that could not be copied
185
+ as plain data was kept as the caller's own object, and a later `add`
186
+ could then fail on it. It is now refused when the writer is opened.
187
+ - The check before acting read the passkeys it trusts once for the
188
+ book and again for its decision. It now reads its options once.
189
+ - Three fixes of the seventeenth review are now held by tests. The
190
+ list of threats said that an entry which does not fit made the
191
+ stub writer read its book again from the start; it costs one line's
192
+ check, and the list now says so.
193
+
194
+ - 2026-10-04: faults found by a seventeenth independent review, of the
195
+ sixteenth review's fixes. Each is fixed and each is now a test
196
+ (`test/review17.test.mjs`). In 25,800 random steps the review found
197
+ no action taken after the person's cancellation was handed over, no
198
+ difference between the stub writer's view of its book and a whole
199
+ check, and no line written that made the book fail its check.
200
+ - A sound cancellation handed to `add` wrapped in a Proxy (as some
201
+ user-interface libraries wrap objects) could not be copied, was taken
202
+ as unreadable, and did not stop the writer. This came from the
203
+ sixteenth review's fixes. What cannot be copied as it stands is now
204
+ copied through its canonical text, still read once.
205
+ - An acknowledgement that waits, carried by a copy given at opening,
206
+ was counted neither in the room the writer keeps nor among the
207
+ waiting ones, and could be cut off. It now counts with the waiting
208
+ ones.
209
+ - With the clock failing, an acknowledgement of the agent's own handed
210
+ over with a cancellation the book holds was taken but neither
211
+ written nor handed back. It now waits, and is handed back and
212
+ written as one that could not be written at once.
213
+ - Opening the stub writer with a very long, nearly empty list of
214
+ cancellations took time in proportion to its length. It no longer
215
+ does.
216
+ - A whole check and a carried checker could still read some unusual
217
+ lists in the options differently (a list with its own way of
218
+ walking through itself, or its own `includes`, or of a class). A
219
+ whole check now reads its options through the same fixed copy, and
220
+ a copy's acknowledgements and a slip's disclosures are read place by
221
+ place.
222
+ - A Show said that cancellations were handed over beside it where the
223
+ list was empty. An empty list is now none, as for a whole book.
224
+ - Tests now hold in place the room kept for the writer's own
225
+ cancellations given at opening, and the limit of 100,000 trusted
226
+ blocks.
227
+
228
+ - 2026-10-04: preparing the first publication. The package version is
229
+ 0.1.0. The package holds the library, the command-line checker, the
230
+ format description, the list of threats, the sample record, the
231
+ checking page, the licences, the README and this change log; the
232
+ tests and the demonstration stay in the repository. The README now
233
+ says, as the list of threats did, that no complete block time-stamp
234
+ from a real service has been checked yet.
235
+
236
+ - 2026-10-04: faults found by a sixteenth independent review, of the
237
+ fifteenth review's fixes. Each is fixed and each is now a test
238
+ (`test/review16.test.mjs`). In 9,600 random steps the review found no
239
+ action taken after the person's cancellation was handed over (but for
240
+ the case below of a member whose value changes), no line written that
241
+ made the book fail its check, and no difference between the stub
242
+ writer's view of its book and a whole check.
243
+ - An acknowledgement that waits to follow its cancellation into the
244
+ book could be cut off by cancellations kept after it, and copies of
245
+ other slips' cancellations given at opening could crowd out the
246
+ writer's own. The writer now holds its own slip's cancellations
247
+ first, then the acknowledgements that wait, then the other copies,
248
+ which give way.
249
+ - `add` read what it was handed more than once: a member whose value
250
+ changed from one reading to the next could leave the writer
251
+ unstopped. It is now read once, member by member.
252
+ - An option, or a place in a list, that cannot be read made a carried
253
+ checker and the stub writer crash where a whole check answers. It
254
+ now fails exactly where a whole check reads it; the stub writer
255
+ refuses such options when it is opened.
256
+ - The list of blocks and a copy's time-stamps were read through a
257
+ list's own way of walking through itself; they are now read place
258
+ by place. A very long list with no items in it made a carried
259
+ checker hang; only the places that hold an item are now copied, and
260
+ the list of blocks holds at most 100,000.
261
+ - A copy of a cancellation given at opening as an object of a class
262
+ was changed by the writer, and one that was frozen made every `add`
263
+ fail. Such a copy is now copied as plain data.
264
+ - A writer opened from a book with two acknowledgements of its own
265
+ agent handed back the second; a copy given at opening could end up
266
+ with two. The first is taken, and a copy takes no second one.
267
+ - The empty list that a writer holding no cancellation hands back was
268
+ refused when it was handed in again. An empty list of cancellations
269
+ is now accepted as none.
270
+ - Of the time-stamps the writer counts on a cancellation it holds, the
271
+ earliest are now kept.
272
+ - The documents now say that a writer keeps every cancellation of its
273
+ slip, and that where the clock fails the error is the clock's own.
274
+
275
+ - 2026-10-04: the checking page tried again in current browsers: three
276
+ test builds and two installed desktop browsers at version 154, with
277
+ and without experimental features. None has ML-DSA or SLH-DSA built
278
+ in; each says plainly that the check is not complete, and none shows
279
+ a pass. No horizontal scrolling at phone width. The page built as one
280
+ file refused every request made from inside it. One fault, fixed: in
281
+ the page built as one file, a record chosen before the page's script
282
+ had started was ignored without a word (seen in one browser build). A
283
+ record already chosen when the script starts is now checked.
284
+
285
+ - 2026-10-04: faults found by a fifteenth independent review, of the
286
+ fourteenth review's fixes. Each is fixed and each is now a test
287
+ (`test/review15.test.mjs`). In 2,500 random calls the review found no
288
+ action taken after the person's cancellation was handed over, no line
289
+ written that made the book fail its check, and no difference between
290
+ the stub writer's view of its book and a whole check.
291
+ - A list with a gap in it, beside a cancellation, was written as text
292
+ that is not JSON. With the clock failing, the cancellation was then
293
+ lost: a writer opened again took actions. A list with a gap is now
294
+ refused as not JSON (`payload-not-canonical`), and the sound
295
+ time-stamps in such a list are still kept.
296
+ - A time-stamp from a service the writer was not told to trust, kept
297
+ with a cancellation, kept out a trusted one handed over later; so
298
+ did a trusted one that was late. The writer now merges the
299
+ time-stamps it holds with those handed over: each is judged by
300
+ itself, the ones it counts come first, four at most. Of a list with
301
+ a faulty time-stamp in it, the sound ones are kept.
302
+ - With the clock failing, the acknowledgements handed over with a
303
+ cancellation were dropped, and a writer signed a second one later. A
304
+ copy could hold two acknowledgements of the writer's own agent, and
305
+ a writer opened again took the last of them where `add` took the
306
+ first. They are now kept on a clock failure; only the first of the
307
+ agent's own is taken, everywhere; the agent's own is found among more
308
+ than four.
309
+ - A copy of a cancellation given at opening with a member that is not
310
+ enumerable was checked with it and handed back without it. Such a
311
+ copy is now made plain data before it is checked.
312
+ - The copy of the options read a member that a whole check never
313
+ reads, and turned a gap in a list into an empty place. A member that
314
+ cannot be read is now kept as it is, and a gap stays a gap; a gap in
315
+ the list of blocks, or of a copy's time-stamps, is refused.
316
+ - Where a kept cancellation was written into the book in the same
317
+ call, the error said it was not added. It now says what was done.
318
+ - An acknowledgement still waiting to follow its cancellation into the
319
+ book was not handed back, and was lost to a writer opened again. It
320
+ is now handed back with the cancellation, and written by a writer
321
+ opened again.
322
+ - With the clock failing, the error for a cancellation that cannot be
323
+ kept, because the writer already holds 16, now says so.
324
+ - Tests now hold in place nine fixes of the fourteenth review that
325
+ could be undone without any test failing. Each fix of this review,
326
+ and each of those nine, was then undone in turn in a copy of the
327
+ code: a test caught every one.
328
+
329
+ - 2026-10-04: faults found by a fourteenth independent review, of the
330
+ thirteenth review's fixes. Each is fixed and each is now a test
331
+ (`test/review14.test.mjs`). In 3,000 random calls the review found no
332
+ action taken after the person's cancellation was handed over, no line
333
+ written that made the book fail its check, and no difference between
334
+ the stub writer's view of its book and a whole check.
335
+ - `add`, handed a cancellation with several acknowledgements, could
336
+ take one that does not check (signed with other keys, or given for
337
+ another cancellation) as its own agent's, hand it back, and keep it
338
+ with the cancellation, so that nothing more could be added to the
339
+ book. Each acknowledgement is now checked by itself, and only one
340
+ that checks is taken.
341
+ - A sound time-stamp on a cancellation was lost where the clock
342
+ failed, and where it was handed over only after the date of a kept
343
+ cancellation had come. The writer now keeps the cancellation with
344
+ its sound time-stamps, and takes a time-stamp into a kept
345
+ cancellation before it writes anything into the book.
346
+ - Where a copy already held four acknowledgements of helper agents,
347
+ the writer's own was handed back and not kept, and a writer opened
348
+ again signed a second one. The writer's own is now always kept; the
349
+ last of the others gives way. Sound acknowledgements of other agents
350
+ that come with a cancellation stay with the kept copy.
351
+ - A member that is not enumerable, one level down in the options, was
352
+ made enumerable by a carried checker, which then refused what a
353
+ whole check does not see. It now stays as it was.
354
+ - A tool's function that kept the object it gave as `amount`, or the
355
+ list it gave as `details`, could change it before the second try,
356
+ after the person's approval. What these functions give is now
357
+ copied. Each member of a tool's description is read once.
358
+ - The error for a cancellation that cannot be kept, because the writer
359
+ already holds 16, now says so.
360
+
361
+ - 2026-10-04: faults found by a thirteenth independent review, of the
362
+ eleventh and twelfth reviews' fixes. Each is fixed, or stated, and
363
+ each is now a test (`test/review13.test.mjs`). The review found no way
364
+ to make a whole book or a Show read as intact, or as within its slip,
365
+ when it is not, and no way to make the stub writer's view of its book
366
+ differ from a whole check.
367
+ - The stub writer could date its acknowledgement before a pass that
368
+ its agent had handed on (a pass may be dated up to 300 seconds
369
+ ahead of the clock), so that an honest pass, and the stubs under
370
+ it, read as made after the agent was told. It no longer does.
371
+ - A tool's own function could change what the tool was recorded as,
372
+ through `this`. Each function is now called by itself, and the
373
+ description is frozen.
374
+ - A cancellation given when the writer was opened was handed back
375
+ without the acknowledgement signed for it, and did not take a
376
+ time-stamp handed over later. It now does both, and stops the
377
+ writer from the start.
378
+ - `add`, handed the form that `cancellations()` gives back, dropped a
379
+ sound time-stamp. It now adds the cancellation with its
380
+ time-stamps, and goes on handing back an acknowledgement of its own
381
+ agent that came with it.
382
+ - A clock that failed while the person's cancellation was handed over
383
+ lost the cancellation, and the writer acted on. The writer is now
384
+ stopped, and keeps the cancellation, before the clock is read.
385
+ - A clock that gave no time (`NaN`) switched off the rule that
386
+ nothing is written dated ahead of the clock. It now counts as a
387
+ clock that failed.
388
+ - An acknowledgement dated ahead of the clock was never written into
389
+ the book. It is now tried again.
390
+ - The words a stub was given depended on the order of the
391
+ acknowledgements in one copy. They no longer do.
392
+ - A member of the options that is not enumerable was dropped by a
393
+ carried checker and read by a whole check. Both now read it.
394
+ - `argumentsFingerprint` threw at once for arguments that are not
395
+ JSON; it now refuses through its promise. Stated: `0` and `-0`
396
+ share a fingerprint, as RFC 8785 sets out.
397
+
398
+ - 2026-10-04: the author is named in the format description's copyright
399
+ line, in the README and in `package.json`.
400
+
401
+ - 2026-10-04: faults found by a twelfth independent review, of the
402
+ acknowledgement and of the connector for an agent's tools. Each is
403
+ fixed and each is now a test (`test/review12.test.mjs`). The review
404
+ found no way to have an acknowledgement counted that the agent's side
405
+ did not sign, to have a stub excused through one, or to run a tool
406
+ that the slip does not allow.
407
+ - The stub writer could date its acknowledgement before its own last
408
+ stub (a stub may be dated up to 300 seconds ahead of the clock), so
409
+ that an honest stub read as made after the agent was told. It no
410
+ longer does.
411
+ - Different arguments could share one fingerprint: a list with a gap
412
+ in it, or with a named member, was written as if it had neither. It
413
+ is now refused as not JSON, and the tool is not run.
414
+ - What a tool is was copied one level deep, and one object went to
415
+ all of a tool's functions and then to the tool. Each now gets a copy
416
+ of its own, and a tool's description is fixed through and through.
417
+ - The person was asked to approve an action that could not be taken
418
+ anyway (the slip also asks for a countersignature, and the tool has
419
+ no way to ask for one). They are no longer asked, and the stub
420
+ writer's answer names both things that are missing.
421
+ - An acknowledgement in a book still passed after the cancellation it
422
+ names had failed its check further on in the book. It no longer
423
+ does (`cancellation-not-found`).
424
+ - Which words a stub was given depended on the order in which copies
425
+ were handed over. The time-stamp rule is now applied first, for
426
+ every copy; a stub it reports keeps that finding, and is told in
427
+ addition where it is also dated after the acknowledgement.
428
+ - An acknowledgement was given as confirmed where the device could
429
+ not confirm the slip or the copy. It is now given as not checked.
430
+ The command-line checker no longer shows what such a copy says.
431
+ - Changed after the reviewer's design remarks: a pass handed on after
432
+ the agent's side acknowledged, every pass handed on from it, and
433
+ every stub under them, are reported; an acknowledgement that does
434
+ not check is still a problem with the whole check, but the person's
435
+ copy of the cancellation is used all the same; a stub writer opened
436
+ with keys that are not the agent's hands back no acknowledgement.
437
+ - The type declarations said that `cancellations()` hands back
438
+ cancellations with their time-stamps only. They now say that each
439
+ comes with the acknowledgement the writer signed.
440
+
441
+ - 2026-10-04: faults found by an eleventh independent review, of the
442
+ checker that can be carried on, of the stub writer that carries its
443
+ book on, and of the tenth review's fixes. Each is fixed, or stated as
444
+ a limit, and each is now a test (`test/review11.test.mjs`). In 240
445
+ random books the reviewer's carried checker never differed from a
446
+ whole check, and in 2,483 random calls the stub writer never differed
447
+ from a whole check of its book.
448
+ - A clock that failed part of the way through `add` left the stub
449
+ writer's reader holding a line that its book did not. Every line is
450
+ now tried on a reader split off the book's own, which takes the
451
+ book's place only if the line is written. An entry that does not
452
+ fit now costs one line's check, where it cost a reading of the
453
+ whole book.
454
+ - Options that were inherited, worked out when asked for, or objects
455
+ of a class were dropped or changed when a carried checker or the
456
+ stub writer copied them, so that the answer could differ from a
457
+ whole check's. They are now read once, as a whole check reads them.
458
+ - A new rule: a seal dated more than 300 seconds before a time-stamp
459
+ that it covers (a service's time-stamp on a seal before it) is
460
+ reported (`time-went-backwards`). Stated beside it: what a Show
461
+ cannot show where the earlier seal is left out of its pages.
462
+ - A cancellation given when the stub writer is opened is now written
463
+ into the book once its date has come; every cancellation of its
464
+ slip that the writer is handed is kept, not only the first; one
465
+ kept without a time-stamp takes the time-stamp it is handed over
466
+ with later; and `cancellations()` hands each back with the
467
+ acknowledgement the writer signed, so that a writer opened again
468
+ hands back the same one.
469
+
470
+ - 2026-10-04: the checking page as one file. `node
471
+ tools/make-single-page.mjs` writes `provared-check.html`: the page, its
472
+ style, the checker and the sample record in one file, copied in
473
+ unchanged, which opens in a browser from the disk with no server. Its
474
+ content security policy allows no request of any kind. Tests:
475
+ `test/single-page.test.mjs`. Tried in three browser builds.
476
+
477
+ - 2026-10-04: a connector between an agent's tools and the stub writer.
478
+ `recordTools(recorder, tools)` puts each tool behind the stub writer:
479
+ a call asks first, runs the tool only if the slip allows the action,
480
+ and writes the stub. A call that is not allowed throws `NotTaken`.
481
+ Where the slip asks for the person's approval, the tool's `approve`
482
+ function is asked for it once. By default the stub names one
483
+ document, `arguments`: the fingerprint of the call's arguments,
484
+ written in the one form of RFC 8785 (`argumentsFingerprint`). It
485
+ names no agent software. Tests: `test/tools.test.mjs`.
486
+
487
+ - 2026-10-04: the acknowledgement, a new kind of record (format
488
+ description, section 26). The agent's side states, with the agent's
489
+ own keys, that it was handed the person's cancellation of a slip, and
490
+ when. A cancellation shows when the person signed it; until now
491
+ nothing showed that the agent's side was told.
492
+ - The record: `provared.acknowledgement.v0`, with the label
493
+ `vnd.provared.acknowledgement.v0+json`, signed with the two keys of
494
+ the slip's agent, or of a helper agent under its pass.
495
+ `writeAcknowledgement` writes one.
496
+ - In a book it is an entry of its own, `{"acknowledgement": ...}`,
497
+ after the cancellation it names. A new code:
498
+ `cancellation-not-found`.
499
+ - The person hands it to a checker with their own copy of the
500
+ cancellation (`acknowledgements`, up to four). Every stub of that
501
+ agent dated after the acknowledgement is then reported, in words of
502
+ its own, even where the copy has no time-stamp. Where the book
503
+ leaves the cancellation out, the checker says that the agent's side
504
+ had acknowledged it. A new code: `acknowledgement-mismatch`.
505
+ - The stub writer signs an acknowledgement whenever the person's
506
+ cancellation of its slip is handed to `add`, writes it into the book
507
+ after the cancellation, and hands it back: in the answer of `add`,
508
+ or in the `acknowledgement` member of the error where `add` fails.
509
+ - The checker's answer: a new kind of entry, `acknowledgement`; a new
510
+ count, `summary.counts.acknowledgements`; and `acknowledgements` on
511
+ each cancellation handed over beside the book. The command-line
512
+ checker and the checking page show them.
513
+ - Tests: `test/acknowledgement.test.mjs`, and the two new codes in
514
+ `test/refusals.test.mjs`.
515
+
516
+ - 2026-10-04: a checker that can be carried on. No record and no rule of
517
+ the format changes: only how fast the free library works.
518
+ - `openChecker(book, options)` reads a book once and then takes more
519
+ lines (`add`), without reading the earlier ones again. Its answer
520
+ (`result`) is the answer `checkBook` gives for the same text. A
521
+ whole check is now: start, read every line, give the answer; there
522
+ is one way of reading a line.
523
+ - The stub writer carries its book on. One action no longer checks
524
+ every signature in the book twice. Measured on one computer, with
525
+ countersigned stubs: 9, 14 and 23 thousandths of a second for one
526
+ action after 400, 1,600 and 6,400 stubs, where it took 2.0 seconds
527
+ after 400 and 7.7 after 1,600.
528
+ - `recorder.check()` gives the checker's answer for the writer's book
529
+ as it stands. `recorder.before()` now waits its turn with the other
530
+ calls.
531
+ - What can be found only once every stub has been read (a limit "in
532
+ any period", what a cancellation handed over beside the book shows)
533
+ is worked out afresh for each answer, and is no longer written into
534
+ what the checker keeps while it reads.
535
+ - New tests (`test/carried.test.mjs`): the carried checker against a
536
+ whole check after every line of a book with every kind of entry;
537
+ trying a stub leaves the book's reader as it was; the stub writer's
538
+ view of its book against a whole check after every call.
539
+
540
+ - 2026-10-04: faults found by a tenth independent review, of the ninth
541
+ review's fixes. Each is fixed, or stated as a limit, and each is now a
542
+ test (`test/review10.test.mjs`). With time-stamps that tell the truth,
543
+ the review found no way to make a whole book or a Show read as intact,
544
+ or as within its slip, when it is not, apart from the two narrow cases
545
+ below (the seal of a Show, and a rare kind of block).
546
+ - The stub writer lost a cancellation that the person had signed when
547
+ something beside it could not be written as a line of a book
548
+ (`stamps: undefined`, for example), and went on taking actions.
549
+ `add` now adds the cancellation by itself where what stands beside
550
+ it is at fault, and the call still fails and says what was done.
551
+ - A cancellation that the stub writer kept, because it was dated ahead
552
+ of the clock, was never written into the book, and a writer opened
553
+ again from the book took actions again. The writer now writes it
554
+ into the book once its clock has reached that date, whole, with the
555
+ person's time-stamps. Until then `cancellations()` hands back what
556
+ the writer holds, to be kept with the book. Stated as a limit: a
557
+ writer opened from the book alone knows nothing of it.
558
+ - A cancellation with no counted time-stamp of its own was shown as
559
+ "counts as cancelled at" the time of a later seal. The checker's
560
+ answer now keeps two times apart: `existedBy`, the time by which a
561
+ later seal shows that an entry existed, and `stampedAt`, the time
562
+ that a seal's or a cancellation's own time-stamps give it. **This
563
+ changes the answer's shape:** for a slip, a stub and the other kinds
564
+ of entry, what was `stampedAt` is now `existedBy`.
565
+ - The seal that comes with a Show was not held to the rule that no
566
+ unique number appears twice. It now is, against the pages.
567
+ - A block time-stamp beside a later seal that stated a time before a
568
+ service's time-stamp on an earlier seal was credited, and could
569
+ excuse a stub made after a cancellation. It is now set aside, and
570
+ the checker says so. It needs a block that states a time far behind
571
+ the true time.
572
+ - A seal or a cancellation that did not pass its check no longer shows
573
+ a time of its own.
574
+ - A date was reported against the time-stamp of a cancellation whose
575
+ passkey signature the device could not check. It no longer is, as
576
+ for a seal.
577
+ - The format description and the list of threats said that a page
578
+ dated after a seal's time-stamp is the page reported in a Show. The
579
+ seal is.
580
+
581
+ - 2026-10-03: faults found by a ninth independent review, of the eighth
582
+ review's fixes. Each is fixed, or stated as a limit, and each is now a
583
+ test (`test/review9.test.mjs`). The review found no way to make a
584
+ whole book read as intact, or as within its slip, when it is not.
585
+ - A cancellation dated ahead, put into a block at once and
586
+ time-stamped by a service on its date, counted from the block's
587
+ time: days before the date the person signed. Honest stubs were then
588
+ reported. A cancellation is now never taken to have been made before
589
+ its own date, and the checker says that the two time-stamps do not
590
+ agree.
591
+ - A seal with an early block time-stamp and a later one from a service
592
+ counted from the later. Every counted time-stamp of a seal is now
593
+ taken, and the earliest counts. A block that states a time long
594
+ before the seal's own date, beside a service's time-stamp, is still
595
+ set aside, and the checker says so.
596
+ - In a Show, an old seal that did not belong to the book marked the
597
+ honest page before it. The finding is now given for the seal.
598
+ - In a Show, a seal was not held to the chain of seals. It now is, as
599
+ far as the pages show the chain.
600
+ - The stub writer wrote an approval dated up to 600 seconds ahead of
601
+ its clock. It now writes none dated more than 300 seconds ahead.
602
+ - The stub writer kept at most 16 cancellations that it could not add,
603
+ of any slip in the book, and dropped the next: its own slip's
604
+ cancellation could be the one dropped. It now keeps one, of its own
605
+ slip.
606
+ - Stated as limits in the documents: the time-stamps beside the seal
607
+ of a Show, and beside the last seal of a book, can be swapped for
608
+ later ones (the gain is at most 300 seconds); a person can keep a
609
+ cancellation back and hand it over later; only a late time, not a
610
+ late time-stamp beside a prompt one, is pointed out on a
611
+ cancellation.
612
+
613
+ - 2026-10-03: the checking page takes what the command-line checker
614
+ takes. A fifth box names the blocks you trust. A second panel takes the
615
+ person's own copies of cancellations (up to 16 files) and one file of
616
+ disclosures for covered fields; each handed-over cancellation is shown
617
+ as a card, saying whether the book holds it. A file that is not JSON
618
+ stops the check. The sample record is checked without those files.
619
+ Tried in three browser builds at phone width.
620
+
621
+ - 2026-10-03: faults found by an eighth independent review, of the stub
622
+ writer, of which time-stamps give a record its time, and of ten passes
623
+ in a row. Each is fixed and each is now a test
624
+ (`test/review8.test.mjs`). Passing on up to ten times was found sound.
625
+ - A later time-stamp from a service, put beside an earlier block
626
+ time-stamp on a cancellation, moved the cancellation's time later,
627
+ and excused stubs made after the person cancelled; in the person's
628
+ own copy too. Every counted time-stamp beside a cancellation is now
629
+ taken, and the earliest counts.
630
+ - A block time-stamp on a cancellation is no longer taken as earlier
631
+ than the date the person signed in the cancellation. Before, a stub
632
+ that an outside time-stamp showed to have existed before that date
633
+ could still be reported.
634
+ - Where a service's time-stamp and a block time-stamp beside one seal
635
+ do not agree, the checker now says so.
636
+ - A service's time-stamps could step backwards without end, 300 seconds
637
+ at a time. Each is now compared with the latest before it.
638
+ - A Show under a later seal passed where the whole book failed, even
639
+ with the earlier seal among its pages. A seal among the pages is now
640
+ held against the pages and the seals before it. With that seal left
641
+ out of the pages a Show cannot show it, and the documents now say so.
642
+ - The stub writer wrote its line from the caller's own objects after it
643
+ had checked them, so a later change could put a line into the book
644
+ that failed the book's check. What it is handed is now copied when it
645
+ is handed over.
646
+ - `record` handed the stub to the other side before the check of the
647
+ whole book, so the other side could hold two signed stubs for one
648
+ place in the chain. It now checks first.
649
+ - `act` accepted a date in the past, so an action could be taken after
650
+ the slip had ended and dated inside it. A date handed to `act` must
651
+ now be within 300 seconds of the writer's clock.
652
+ - After an other side that never answered, a later call that stemmed
653
+ from that request was refused as "from inside an action". The mark
654
+ now ends when the time to countersign runs out.
655
+ - A countersignature dated up to 598 seconds ahead of the clock was
656
+ written. It is now compared with the clock alone: 300 seconds.
657
+ - The check before acting refuses an action that would add to a period
658
+ which a later-dated stub already overfills, though a checker reports
659
+ nothing new for it. That stays, and the format description now says
660
+ so, where it said the two agree exactly.
661
+
662
+ - 2026-10-03: a slip may allow up to ten passes in a row (`passes`: 1 to
663
+ 10); an eleventh is refused. It was three. Ten is the upper number
664
+ commonly set for chains of delegated access between services, and is a
665
+ first-draft number.
666
+ - 2026-10-03: faults found by a seventh independent review, of how
667
+ time-stamps are credited and of the stub writer. Each is fixed and
668
+ each is now a test (`test/review7.test.mjs`). The review found no way
669
+ to make a whole book read as intact, or as within its slip, when it is
670
+ not.
671
+ - A Show under a seal passed where the whole book failed: the seal's
672
+ own date was not compared with the pages. It is now.
673
+ - The stub writer refused a cancellation it could not add (a faulty
674
+ time-stamp beside it, a date ahead of the clock) and went on allowing
675
+ actions. A cancellation the person signed now stops it either way.
676
+ - `act` wrote its line without the whole-book check that `record`
677
+ makes. The stub is now written and checked with the whole book
678
+ before the action is taken; the other side is handed a copy of the
679
+ stub; a stub added through `add` moves the writer's place on.
680
+ - An approval that was not a record let the action be taken and then
681
+ lost its stub. It now stops the action before it is taken.
682
+ - The stub writer accepted its own stub dated ahead of its clock. It
683
+ writes nothing dated ahead of it.
684
+ - A call made after an action had ended could be refused as "from
685
+ inside the action". The mark now holds only while the action runs.
686
+ - A later seal was reported because of an entry that had already
687
+ failed its own check, and one misdated entry excused a seal from
688
+ every other. Each entry is now looked at by itself.
689
+ - A date was reported against a time-stamp that the device could not
690
+ count. It no longer is, and the seal says that the time-stamp was
691
+ not counted.
692
+ - Where a service states the time, its time-stamps now give the time,
693
+ and a block time-stamp beside them is a second witness. A block that
694
+ states a time far behind no longer makes such a seal fail.
695
+ - A time limit of "for ever" for the other side became one
696
+ millisecond; it is now refused. An empty list of documents is the
697
+ same as none in `act` as in `record`.
698
+
699
+ - 2026-10-03: faults found by a sixth independent review, of the block
700
+ time-stamp and the stub writer. Each is fixed and each is now a test
701
+ (`test/review6.test.mjs`). The review found no way to have a block
702
+ time-stamp counted without a proof that leads to a block the reader
703
+ named, and nothing that crashed or hung the checker.
704
+ - On a cancellation, a block time-stamp's two hours of looseness were
705
+ taken the unsafe way, so a stub made after the cancellation could
706
+ escape. A cancellation now counts from two hours before the time the
707
+ block states, and the time used is shown.
708
+ - A seal dated before an entry it covers was not reported once any
709
+ counted time-stamp existed, even one that settled nothing. It is now.
710
+ - An entry kept the time of the first seal after it, even where a later
711
+ seal showed an earlier time; naming a true block could then turn an
712
+ honest stub into one "after the cancellation". An entry now has the
713
+ earliest time that any seal after it shows.
714
+ - The stub writer accepted a countersignature, or an entry, dated years
715
+ ahead, after which its book could not be sealed. Both are refused.
716
+ - The stub writer could be blocked for good by an other side that never
717
+ answered, or by a call from inside its own action. The other side now
718
+ has a set time; such a call is refused at once (in Node.js).
719
+ - The stub writer relied on an approval's fingerprint as handed over.
720
+ It now works it out from the approval itself.
721
+ - `record` could write a stub that made the book fail its check. It
722
+ now writes nothing unless the book still passes with it.
723
+ - The check before acting ignored the longest line a book may hold. An
724
+ action whose record would not fit is not allowed.
725
+ - `act` took an action that was certain to be outside the slip, where
726
+ the slip asks for a countersignature and no way to ask for one was
727
+ given. It no longer does.
728
+ - Disclosures handed over beside a Show were ignored where the page
729
+ carried its own. Both are now used together.
730
+ - The note about a late time-stamp on a cancellation appeared for
731
+ almost every block time-stamp. It now goes by the earliest time the
732
+ time-stamp allows.
733
+ - A block's number above about four thousand million was refused,
734
+ against the format description; a header of the wrong length had two
735
+ codes. Both follow the description now, which allows 255 steps in a
736
+ row, as the format's own reader does.
737
+ - Where two passes above a stub both set a limit within a period, the
738
+ checker and the check before acting named different passes. Both now
739
+ name the nearer one.
740
+ - A unit could hold spaces and capitals and be read as the checker's
741
+ own words. A unit is now 1 to 16 characters with no spaces.
742
+ - On a device that cannot check all three signatures of a seal, the
743
+ seal now says that its time-stamp was not counted.
744
+
745
+ - 2026-10-03: the block time-stamp, a second kind of time-stamp beside a
746
+ seal or a cancellation. It is a proof, in the open format
747
+ OpenTimestamps, that the fingerprint was written into a block of the
748
+ Bitcoin blockchain, with the block's header beside it. The chain is
749
+ used purely as a clock: no coin, wallet, account or payment. It rests
750
+ on SHA-256 only, not on a signature. The person checking names the
751
+ blocks they trust by fingerprint (`blocks`, `--block`); a block's time
752
+ counts as right to within two hours. The library sends nothing
753
+ anywhere and names no service. Tested with made-up blocks; published
754
+ sample proofs of the format were read with the reader, and no complete
755
+ proof from a real service has been checked yet.
756
+
757
+ - 2026-10-03: faults found by a fifth independent review, of the fixes
758
+ below and of the person's own copy of a cancellation. Each is fixed and
759
+ each is now a test (`test/review5.test.mjs`). The review found no way
760
+ to make a book or a Show read as intact, or as within its slip, when it
761
+ is not, and nothing that crashed or hung.
762
+ - The stub writer let two actions asked for at the same moment both
763
+ pass the check before acting. Its calls now wait for one another.
764
+ - The stub writer put the other side's countersignature into the book
765
+ unchecked; one made with other keys made the whole book fail. It is
766
+ now checked first, and left out if it does not check. `add` adds an
767
+ entry only if the book still passes its check with it.
768
+ - The check before acting allowed an action that could never be
769
+ countersigned where the slip asks for a countersignature. It no
770
+ longer does.
771
+ - A name padded with the blank Braille pattern could draw a line that
772
+ looked like the checker's own, a variation selector passed unmarked,
773
+ and a name could carry the checker's words. Every character that is
774
+ not drawn is now marked, a name or a purpose is shown in quotation
775
+ marks, and the page folds runs of spaces as the command line does.
776
+ - The signer of a slip could cover a name with a value a slip may not
777
+ hold, so that the slip was sound only while the name stayed covered.
778
+ Disclosures that do not pass are now refused and reported apart, and
779
+ the slip is checked as it would be without them.
780
+ - A finding about a period was given twice on a helper's stub where the
781
+ slip and the pass both set such a limit. It is given once.
782
+ - Only four passes were compared for one stub, so two checkers could
783
+ differ on the totals of a pass far up. A fourth pass in a row is now
784
+ refused (`pass-too-deep`), and a stub is compared with every pass
785
+ above its own.
786
+ - Any text was accepted in the place of a covered field. It must now be
787
+ a SHA-256 fingerprint in base64url.
788
+ - Disclosures handed over in the wrong form were ignored without a
789
+ word. They are now refused.
790
+ - The format description said an action may not be dated before the
791
+ last stub "under the slip"; the code, rightly, uses the last stub of
792
+ its own chain. The description is corrected.
793
+ - The notes about the person's own copy of a cancellation said the book
794
+ left it out where the book held it with a broken time-stamp, and did
795
+ not point out a late time-stamp on the copy. Both are corrected.
796
+ - A finding about a period may be given for a stub of another chain
797
+ than the one written last. That is as the format sets out; it is now
798
+ stated.
799
+
800
+ - 2026-10-03: the person's own copy of a cancellation. The checker takes
801
+ it beside the book (`cancellations`, `--cancellation`). It counts even
802
+ where whoever keeps the book left the cancellation out, or holds it
803
+ with a later time-stamp: every stub that no outside time-stamp shows
804
+ to have existed before it is reported, and the check before acting
805
+ allows nothing under the slip. A copy that does not pass its check is
806
+ a problem, never set aside. The answer has a new member, `held`.
807
+
808
+ - 2026-10-03: faults found by a fourth independent review, of
809
+ cancelling, vouching, covered fields and passing on. Each is fixed and
810
+ each is now a test (`test/review4.test.mjs`). The review found no way
811
+ to crash the checker, and found the checks of who signed a
812
+ cancellation, a vouching record, a withdrawal and a pass sound.
813
+ - A slip could cover an item of a list: a limit, a condition, an
814
+ action, a service or a key. One signed slip then read differently to
815
+ different readers, and the check before acting allowed anything. An
816
+ item of a list can no longer be covered in a slip.
817
+ - A member named `__proto__` in a slip was accepted, hidden from every
818
+ check, and what it held was inherited unchecked: software names sent
819
+ to the terminal as they were, keys for a service that nobody had
820
+ checked, a stand-in for a covered name. It is now a member like any
821
+ other, and is refused as unknown.
822
+ - A limit "within any period" could be emptied by a later-dated stub in
823
+ a helper's chain. A period now goes by the times the stubs state, in
824
+ whichever chain and at whichever place in the book, and is worked out
825
+ once every stub has been read. The check before acting counts the
826
+ periods of later-dated stubs too.
827
+ - Where the person cancelled twice, only the first cancellation in the
828
+ book counted, and whoever kept the book chose the order. Every
829
+ cancellation now counts.
830
+ - A time-stamp beside a cancellation can be swapped for a later one.
831
+ No check can show that; the checker now points out a time-stamp dated
832
+ more than 300 seconds after the cancellation's own date, and the
833
+ documents state the limit.
834
+ - A helper could pass on and so escape the limits, actions and times of
835
+ its own pass. A stub is now compared with every pass above its own,
836
+ and so is an action in the check before acting.
837
+ - A Show applied the strict rule for a time-stamped cancellation, which
838
+ single pages cannot settle, and reported a stub that the whole book
839
+ clears. It now uses only the place of each page, and says so.
840
+ - A Show did not say that a cancellation or a withdrawal may be on a
841
+ page that is not shown. It does now.
842
+ - A vouching record that had run out still stood behind a slip that
843
+ began inside its time. It must now be in force for the whole of the
844
+ slip's time, and for a seal at the time-stamped time too.
845
+ - A pass that the device could not check, with no stub under it, still
846
+ gave "within its slip". It no longer does.
847
+ - Looking up who vouches took time that grew with the number of
848
+ vouching records multiplied by the number of names. It no longer does:
849
+ a book of 45 megabytes that took 46 seconds takes 4.
850
+ - A service whose id is `constructor` was shown as vouched for by
851
+ "undefined". Every service now has a place of its own in the answer.
852
+ - An empty list of covered fields let a name be absent and shown as
853
+ covered. A list now holds exactly one fingerprint, the fingerprint
854
+ method is named exactly where something is covered, and a decoy is
855
+ not accepted.
856
+ - Disclosures handed over with a page that is not a slip were ignored.
857
+ They are now refused; disclosures for a slip that is not there are
858
+ pointed out.
859
+ - The command-line checker and the page did not show how often a slip
860
+ may be passed on. They do now.
861
+ - The type declarations said a covered name is always text, and left
862
+ out the pass on a helper's stub. Both are corrected.
863
+ - Also: a disclosure for a slip must be JSON in the canonical form, so
864
+ that two checkers cannot read one disclosure in two ways.
865
+
866
+ - 2026-10-03: `openRecorder`, the stub writer beside an agent. It keeps the
867
+ agent's place in its chain, asks the check before acting, takes the
868
+ action only if the answer is yes, and writes the stub.
869
+ - 2026-10-03: faults found by a third independent review, of the seal
870
+ and the time-stamp. Each is fixed and each is now a test
871
+ (`test/review3.test.mjs`). The review found no way to have a time-stamp
872
+ counted without the trusted service's key, and nothing that crashed.
873
+ - A Show under a seal did not report a page dated after the time-stamp
874
+ that covers it. It does now, for a countersignature's and an
875
+ approval's date too.
876
+ - A seal shown as a single page was compared with nothing. Its place is
877
+ now checked, the page says it could not be compared, and its
878
+ time-stamp is credited to no other page.
879
+ - On the checking page, a line that was not a fingerprint was dropped,
880
+ which switched the check off. It now stops the check and says which
881
+ box.
882
+ - A time-stamp from a service nobody named could make a sound record
883
+ fail. It is now compared with nothing.
884
+ - A time-stamp is now read in full and must be strict DER, laid out as
885
+ its standards set out. It must name the certificate that signed it,
886
+ in its signed part; that certificate, wherever it sits, is the one
887
+ that counts. A time-stamp that states its time too loosely, or carries
888
+ an extension it insists on, is refused.
889
+ - A seal dated before an entry it covers, and a later seal time-stamped
890
+ before an earlier one, are reported.
891
+ - A time-stamp is credited only when all three signatures of the seal
892
+ were checked.
893
+ - A name padded with spaces could wrap into a line that looked like the
894
+ checker's own. Runs of spaces are now shown as one.
895
+ - Smaller: the same time-stamp twice is refused; checking a time-stamp
896
+ no longer changes the caller's copy; a small file can no longer cost
897
+ much work.
898
+ - 2026-10-03: passing a slip on. A slip can allow its agent to hand part
899
+ of its permission to a helper agent, up to three times in a row. The
900
+ pass is a new record, signed by the agent that passes on. A helper's
901
+ stubs form a chain of their own and are compared with the pass and with
902
+ the slip; the slip's totals take in the agent and every helper
903
+ together. New codes: `pass-missing`, `pass-mismatch` (refused);
904
+ `pass-not-allowed`, `pass-wider` (reported).
905
+ - 2026-10-03: covered fields. A slip can be written with its names and
906
+ its purpose covered, by the standard "Selective Disclosure for JSON Web
907
+ Tokens" (RFC 9901) as it stands. A reader sees a covered field only if
908
+ handed its disclosure; the signature, the chain and the tree check
909
+ either way. The standard's worked example is a test, with every case
910
+ the standard says must be rejected. New: `prepareSlip(fields, { cover })`,
911
+ the `disclosures` option, disclosures on a page of a Show,
912
+ `--disclosures`, and the code `cover-invalid`.
913
+ - 2026-10-03: type declarations for the whole library, for the checker
914
+ alone and for the browser's passkey part. Checked once with a type
915
+ checker against a developer's use of the library; a test keeps them in
916
+ step with what the library exports.
917
+ - 2026-10-03: cancelling a slip, and vouching for a name.
918
+ - The person who signed a slip can cancel it with the same passkey, and
919
+ have the cancellation time-stamped at once. Stubs after it are
920
+ reported (`after-cancellation`). With a time-stamp on the
921
+ cancellation, a stub counts as earlier only if an outside time-stamp
922
+ shows that it existed by then.
923
+ - A vouching record: an organisation states that a key belongs to a
924
+ name, for a person, an agent, a service or a recorder. The person
925
+ checking says which organisations they trust (`vouchers`,
926
+ `--voucher`), and a name those vouch for is shown as vouched for.
927
+ The organisation can withdraw the record.
928
+ - A slip may state the fingerprints of the agent's program and
929
+ settings. It is shown as a statement, not as proof of what ran.
930
+ - Three new records, with their own labels: the cancellation, the
931
+ vouching record and the withdrawal.
932
+ - 2026-10-03: faults found by a second independent review, of the
933
+ framework of limits. Each is fixed and each is now a test. The review
934
+ found no way to make a whole book read as intact, or as within its
935
+ slip, when it was not.
936
+ - The check before acting allowed an action dated before the last stub,
937
+ which then broke the book. It allowed an action on a device that
938
+ could check only one signature of two. It allowed an action under a
939
+ slip signed by any key. It now refuses all three, must be told whose
940
+ passkey it trusts, and where the slip asks for the person's approval
941
+ allows the action only with the signed approval in hand.
942
+ - A Show did not say that single pages cannot show an approval used
943
+ twice. It now says so.
944
+ - A stub or a refusal under a slip that the device could not confirm
945
+ was shown as if it were evidence. It is now hidden.
946
+ - A service's terms signed by a stranger, under the service's name,
947
+ were shown with nothing to tell them apart. Terms and refusals now
948
+ show the fingerprint of the keys that signed them.
949
+ - An approval's own date was compared with nothing and shown nowhere.
950
+ It is now shown, and an approval dated later than its stub is
951
+ refused (`approval-dated-after-stub`).
952
+ - Characters that cannot be seen (zero-width characters, soft hyphens,
953
+ line separators) passed through to the screen. They are now shown as
954
+ a mark, as control characters already were.
955
+ - The name of an unknown field was copied into the message about it.
956
+ No word from a record goes into a message now.
957
+ - The format description said less than the code about which letters a
958
+ unit and an action name may hold. It now says the same.
959
+ - Smaller: an approval whose number equals another record's number was
960
+ called "reused"; terms could accept what they forbid; a service could
961
+ not write down a refused request for an unlisted reserved name; a
962
+ period kept everything it had ever counted in memory.
963
+ - 2026-10-03: the Seal and the outside time-stamp.
964
+ - A seal is a new record: whoever keeps a book signs its top
965
+ fingerprint and its number of entries, with three signatures
966
+ (Ed25519, ML-DSA-87 and SLH-DSA-SHA2-256s). Each seal names the one
967
+ before it.
968
+ - A seal may carry up to four time-stamps in the standard form of RFC
969
+ 3161. The checker reads them offline with a small strict reader of
970
+ its own, and trusts a service only by the fingerprint of its
971
+ certificate, which the person checking gives. No service is named
972
+ anywhere.
973
+ - The latest stubs before a seal can no longer be removed unnoticed. An
974
+ entry dated later than the time-stamp that covers it is reported.
975
+ - A Show can be made under a seal, and then proves when its pages
976
+ existed with no other copy of the top fingerprint.
977
+ - New options: `sealKeys`, `stampServices`, `--sealer`,
978
+ `--stamp-service`. The checking page has boxes for what the person
979
+ trusts.
980
+ - Tested against time-stamps made by the OpenSSL program.
981
+ - What is still open: the last seal, with everything after it, can be
982
+ removed unnoticed, unless someone else holds a copy.
983
+ - 2026-10-03: a framework of limits, in five layers.
984
+ - Amounts: besides a total, a slip can limit each single action, the
985
+ number of actions, and a total or a number within any period.
986
+ - Boundaries: a slip can ask that the other side countersign an action.
987
+ - Approvals: a slip can ask for the person's own approval of an action,
988
+ always or above an amount. The approval is a new record, signed with
989
+ the same passkey as the slip, for exactly one action.
990
+ - Stated rules: a slip can name kinds of action the agent must never
991
+ do, which a checker compares with the stubs, and rules of conduct,
992
+ which are the person's signed instruction.
993
+ - The other side's records: a service can sign a refusal, and its terms
994
+ for agents. Both are new records.
995
+ - A shared list of 30 action names in 8 kinds, a first draft. Names
996
+ that begin `provared.` are reserved for it.
997
+ - `checkBefore`: would this action be outside the slip? It uses the
998
+ checker's own comparison.
999
+ - The demonstration and the sample record show all of these. The
1000
+ person approves one order with the passkey.
1001
+ - Every slip now holds `requires` and `never`, so a draft slip written
1002
+ before this change no longer checks.
1003
+ - 2026-10-03: the quantum-safe method for agents and services is now
1004
+ ML-DSA-87, the strongest of the three strengths of FIPS 204, in place
1005
+ of ML-DSA-65. The test uses the ML-DSA-87 worked example of RFC 9964.
1006
+ The sample record was made again. A key set is larger, so one slip now
1007
+ holds about a dozen services with keys at most.
1008
+ - 2026-10-03: the checking page marks the agent's name and the services'
1009
+ names as labels that are not checked, as it already did for the
1010
+ person's name.
1011
+ - 2026-10-03: faults found by an independent review, each fixed and each
1012
+ now a test.
1013
+ - A small record made with no key crashed the checker (content whose
1014
+ "type" was not text). Nothing from a record is put into a message
1015
+ unchecked any more, and anything the checker does not expect is
1016
+ reported as the problem `check-failed`, never as a pass.
1017
+ - "Intact" was reported on a device that could check no signature. It
1018
+ is now said only when no problem was found and every signature was
1019
+ checked; `summary.problemFound` says whether a problem was found. An
1020
+ entry none of whose signatures could be checked is not shown and not
1021
+ compared with its slip.
1022
+ - A Show reported "within its slip" for a single stub over the limit.
1023
+ - "Every signature checked" was reported when nothing was checked.
1024
+ - A flood of line feeds could end the process. Lines are now counted as
1025
+ they are split.
1026
+ - A trusted top fingerprint was ignored for a book, and a trusted number
1027
+ of entries could not be given: `expectedRoot`, `expectedSize`,
1028
+ `--root`, `--size`.
1029
+ - The writers could make a slip too large for the checker.
1030
+ - `--json` printed characters that can disturb a terminal; the page did
1031
+ not neutralise characters that reorder text.
1032
+ - Smaller: an RSA key of 2,041 bits was accepted; lengths were counted
1033
+ in a way that differs between languages; the threat model said only
1034
+ "the end" of a book could be removed.
1035
+ - 2026-10-03: a damaged record no longer reads as "every signature
1036
+ checked"; what a failed entry says is no longer shown.
1037
+ - 2026-10-03: the pages no longer scroll sideways on a phone; times are
1038
+ shown in words.
1039
+ - 2026-10-03: the first build.
1040
+ - `docs/threat-model.md`: who might attack a record, what each part
1041
+ protects and what it does not, written before the code.
1042
+ - `spec/provared-format.md`: the format, draft version 0: the Slip, the
1043
+ Stub, the countersignature, the chain, the book, the tree and the
1044
+ Show.
1045
+ - `src/`: the checker (`checkBook`, `checkShow`, `checkSlip`) and the
1046
+ writers (`prepareSlip`, `assembleSlip`, `writeStub`, `countersign`,
1047
+ `writeBook`, `makeShow`), with no dependencies. Agents and services
1048
+ sign with Ed25519 and ML-DSA-65 together; a person signs a slip with
1049
+ a passkey.
1050
+ - `bin/provared-check.mjs`: the checker for the command line.
1051
+ - `page/`: the checking page and the demonstration page.
1052
+ - `demo/`: the demonstration, an invented office agent that orders
1053
+ supplies within a limit, with a local server.
1054
+ - `samples/`: a sample record written once, and what a checker must
1055
+ find in it.
1056
+ - `test/`: the tests, including the worked examples of RFC 8032, RFC
1057
+ 8037, RFC 9964 and the test trees of RFC 6962, and one test for every
1058
+ refusal the threat model lists.
1059
+ - Licences: Apache License 2.0 for the code, Creative Commons
1060
+ Attribution 4.0 for the documents.
1061
+ - 2026-10-03: the folder created; no code yet.
1062
+ - 2026-10-03: named Provared.