kxco-pq-audit 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ASSESSMENT.md ADDED
@@ -0,0 +1,122 @@
1
+ # Assessment notes
2
+
3
+ What a buyer assessing this package needs that the README does not tell them:
4
+ where the product boundary falls, what cryptographic agility it has, and what
5
+ constrains its lifecycle.
6
+
7
+ This package does not implement ML-DSA, ML-KEM or SLH-DSA. It calls
8
+ [`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum), which
9
+ runs the NIST ACVP vectors and the cross-implementation interoperability matrix
10
+ and publishes them in its own evidence bundle. Algorithm conformance is a claim
11
+ about that package, is referenced here, and is deliberately not restated. A
12
+ second copy of a conformance claim invites you to count it twice.
13
+
14
+ ## Boundary
15
+
16
+ **What the assessed thing is.** A library that writes and verifies an
17
+ append-only NDJSON file. One storage backend exists, `src/backends/file.js`.
18
+
19
+ **Operate: no network of its own.** Nothing in `src/` opens a socket. Chain
20
+ anchoring happens through a `chain` object the caller injects, so the network
21
+ call belongs to whatever implements it, normally
22
+ [`kxco-pq-chain`](https://www.npmjs.com/package/kxco-pq-chain). Assess that
23
+ package for the connection; this one only calls a method.
24
+
25
+ **Operate: writes are serialised.** Appends run through a promise queue,
26
+ because two appends in flight would read the same tail and mint the same `seq`,
27
+ forking the chain at the point it is supposed to be strongest. That is a
28
+ property of a single process. Two processes appending to one file is not a
29
+ supported configuration and there is no lock that would make it one.
30
+
31
+ **Protect records.** This is the package's whole purpose, so state the parts
32
+ separately:
33
+
34
+ - *Integrity* is a SHA-256 hash chain over entries, plus an ML-DSA-65
35
+ signature. In default mode every entry is signed. In sealed mode entries are
36
+ chained and unsigned, and `seal()` signs the run once, which is what makes
37
+ high append rates affordable.
38
+ - *Timestamps in an entry are the local clock.* They are signed, so they cannot
39
+ be altered after the fact, and a signed clock is still the operator's clock.
40
+ They are not a trusted time source and nothing here claims they are.
41
+ - *The independent time bound is the on-chain checkpoint*, which proves at
42
+ least N entries existed at a given block height. Anchoring is deliberately
43
+ fire-and-forget: `append` does not await it so chain latency never blocks an
44
+ audit write, and a failed anchor writes a warning to stderr while the log
45
+ continues.
46
+
47
+ The consequence is worth stating plainly. A log with no anchor and a log
48
+ whose anchor call failed look identical from the file alone. If the anchor is
49
+ part of your control, monitor that it happened; the log will not tell you.
50
+
51
+ **Start and update.** This package has no release signing of its own. The
52
+ primitives package signs its release assets with ML-DSA-65 against a committed
53
+ public key; this one is an ordinary npm package published through CI with npm
54
+ provenance and nothing further. That is a real difference between the two and
55
+ should not be read across.
56
+
57
+ **Retain history: the limitation that matters.** `verify(publicKey)` takes one
58
+ public key and applies it to the whole log. A log whose signing key was rotated
59
+ part-way through cannot be verified as a single artefact, because entries
60
+ before the rotation were signed by a key `verify` is no longer being given.
61
+
62
+ There is no key identifier in the entry format and no validity window, so the
63
+ package cannot select the right key per entry, and it cannot tell you a key was
64
+ still trusted when a signature was made. Long-lived logs need either one key
65
+ for the life of the log, or a segmentation strategy the caller imposes from
66
+ outside. This is the open long-term-validation question for the KXCO stack and
67
+ it is not solved here.
68
+
69
+ ## Agility
70
+
71
+ Inherited, with one addition and one hard limit.
72
+
73
+ **Inherited.** The signature primitive, its two interchangeable backends and
74
+ the parameter-set surface all belong to `kxco-post-quantum`. See that package's
75
+ `AGILITY.md`. Nothing in this package constrains which backend runs.
76
+
77
+ **The addition: the format carries a version.** Signed bytes are domain
78
+ separated and prefixed, `kxco-audit-v1` for entries and `kxco-audit-seal-v1`
79
+ for seals. A v2 entry format can therefore be introduced without a v1 signature
80
+ becoming ambiguous, which is the property a format migration needs.
81
+
82
+ **The limit: the algorithm is not selectable.** Entries are signed with
83
+ ML-DSA-65 and there is no algorithm field in the entry. A move to a different
84
+ parameter set is a format change and a release of this package, not a
85
+ configuration. Given the file is the artefact and old entries have to keep
86
+ verifying, that is the conservative choice, and it is a ceiling rather than a
87
+ feature.
88
+
89
+ ## Lifecycle
90
+
91
+ **Supported versions.** One line moving forward, matching the rest of the
92
+ family. Fixes land in the next release rather than being backported.
93
+
94
+ **The primitives are declared as a range, and that is the assessed-configuration
95
+ problem.** This package declares `kxco-post-quantum` as `^1.3.0`. The primitives
96
+ package states, in its own `SECURITY.md`, that a range would let the code that
97
+ runs the cryptography change without a release, and pins its own dependencies
98
+ exactly for that reason. We do not apply the same rule here.
99
+
100
+ The practical effect is measurable rather than theoretical: the tree this
101
+ package's evidence bundle was last built from resolved `^1.3.0` to **1.4.0**,
102
+ old enough to predate `backend()`, so it could not even report which
103
+ implementation performed the signatures. `02-primitives.json` in the bundle
104
+ records the resolved version for exactly this reason. Read it before treating
105
+ any claim here as applying to your install.
106
+
107
+ Changing this is a policy decision with a maintenance cost: an exact pin means
108
+ every primitives release needs a release of this package. It has not been made.
109
+
110
+ **Ceiling.** No hardware ceiling. One storage backend, and reads are line by
111
+ line, so search belongs in a database you index into rather than here. The
112
+ practical limit is append throughput in default mode, where every entry is
113
+ signed; sealed mode exists because that limit is real.
114
+
115
+ **Roadmap.** No external audit of this package, no bug bounty, no module
116
+ certification. The primitives package publishes its roadmap in `AUDIT.md`;
117
+ nothing equivalent has been committed for this one.
118
+
119
+ ## Correcting this document
120
+
121
+ Every claim here is checkable against `src/`. If one does not match, that is a
122
+ defect worth reporting through the repository's issues.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.1
4
+
5
+ Documentation and a dependency refresh. No source change.
6
+
7
+ **ASSESSMENT.md.** Where this package's boundary falls, what cryptographic
8
+ agility it has beyond what the primitives provide, and what constrains its
9
+ lifecycle. It references the `kxco-post-quantum` evidence rather than restating
10
+ it, because a second copy of a conformance claim invites the reader to count it
11
+ twice.
12
+
13
+ **`npm run evidence` now exists.** The README already told you to run it and
14
+ there was no such script, so the command failed for anyone who followed it.
15
+ The bundle records identity, this package's own tests, its SBOM, registry
16
+ signature verification, and the `kxco-post-quantum` version actually installed
17
+ rather than the range declared.
18
+
19
+ **`kxco-post-quantum` refreshed to 1.7.2**, from 1.4.0 in the previous
20
+ lockfile. Within the existing range, so no declared dependency changed. Tests
21
+ pass unchanged.
22
+
3
23
  ## 1.3.0
4
24
 
5
25
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kxco-pq-audit",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Tamper-evident post-quantum audit log for regulated institutions. ML-DSA-65-signed, SHA-256 hash-chained entries, so any tampering breaks the chain and shows exactly where. Checkpoint to Armature L1 for an anchor a regulator can confirm on-chain.",
5
5
  "keywords": [
6
6
  "post-quantum",
@@ -53,7 +53,8 @@
53
53
  "CHANGELOG.md",
54
54
  "LICENSE",
55
55
  "README.md",
56
- "src"
56
+ "src",
57
+ "ASSESSMENT.md"
57
58
  ],
58
59
  "engines": {
59
60
  "node": ">=20.19"
@@ -63,7 +64,8 @@
63
64
  "kxco-post-quantum": "^1.3.0"
64
65
  },
65
66
  "scripts": {
66
- "test": "node --test --test-timeout=30000 test/audit.test.js"
67
+ "test": "node --test --test-timeout=30000 test/audit.test.js",
68
+ "evidence": "node scripts/build-evidence.mjs"
67
69
  },
68
70
  "funding": "https://kxco.ai",
69
71
  "publishConfig": {