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 +122 -0
- package/CHANGELOG.md +20 -0
- package/package.json +5 -3
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.
|
|
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": {
|