@open-charging-cloud/wwcp-poi 0.1.1 → 0.2.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.
- package/CHANGELOG.md +498 -454
- package/README.md +522 -362
- package/dist/history/commit.d.ts.map +1 -1
- package/dist/history/epoch.d.ts +2 -0
- package/dist/history/epoch.d.ts.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1404 -278
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +2 -0
- package/dist/keys.d.ts.map +1 -1
- package/dist/proofs/stationProof.d.ts +2 -0
- package/dist/proofs/stationProof.d.ts.map +1 -1
- package/dist/proofs/trustContext.d.ts +6 -0
- package/dist/proofs/trustContext.d.ts.map +1 -1
- package/dist/verifier/chargingStation.d.ts +5 -0
- package/dist/verifier/chargingStation.d.ts.map +1 -1
- package/dist/verifier/documentKeys.d.ts +27 -0
- package/dist/verifier/documentKeys.d.ts.map +1 -0
- package/dist/verifier/historicalMeasurements.d.ts +96 -0
- package/dist/verifier/historicalMeasurements.d.ts.map +1 -0
- package/dist/verifier/measurementKeys.d.ts +48 -0
- package/dist/verifier/measurementKeys.d.ts.map +1 -0
- package/dist/verifier/observedVersions.d.ts +70 -0
- package/dist/verifier/observedVersions.d.ts.map +1 -0
- package/dist/verifier/pricePublication.d.ts +74 -0
- package/dist/verifier/pricePublication.d.ts.map +1 -0
- package/dist/verifier/sessionPrices.d.ts +75 -0
- package/dist/verifier/sessionPrices.d.ts.map +1 -0
- package/dist/verifier/trustTransitions.d.ts +67 -0
- package/dist/verifier/trustTransitions.d.ts.map +1 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,454 +1,498 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## Unreleased
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
`
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
what
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
property
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
its
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
the
|
|
204
|
-
|
|
205
|
-
The
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
`
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
The
|
|
275
|
-
|
|
276
|
-
`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
a new
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
`
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
change set
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
`
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
certificate
|
|
391
|
-
and
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
`
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
its
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
of
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
`
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 0.2.0 (prepared; not yet published)
|
|
7
|
+
|
|
8
|
+
Shared trust and session verification APIs, previously delivered as the unpublished 0.1.2-dev.0 development candidate.
|
|
9
|
+
The experimental evidence and delegation profiles described below remain experimental in this release.
|
|
10
|
+
|
|
11
|
+
- Shared association of an EVSE, its energy meter and its key, with an explicit normalization of SubjectPublicKeyInfo
|
|
12
|
+
and COSE P-256 keys and a conservative freshness of the observation; no claim of a historical association.
|
|
13
|
+
- Historical meter evidence per reading, and checkpoints verified under the current local authorization.
|
|
14
|
+
- Prices bound to a session, their publication and their rates checked apart.
|
|
15
|
+
- A shared comparison of authenticated versions: rollback and fork constraints the caller keeps durably, historical and
|
|
16
|
+
current versions told apart, gaps filled, a change of the epoch refused unless verified.
|
|
17
|
+
- The charging document keys of a CPO, an authority of their own; experimental delegation of a policy signed by two
|
|
18
|
+
quorums, historical timelines of authorities, and verified epoch continuation and profiles.
|
|
19
|
+
- Experimental receipts of a public retrieval of prices, a policy of witness organizations, networks and clocks of
|
|
20
|
+
its own, restrictions of key usages and a conservative result before the signed start; no witness authorized
|
|
21
|
+
automatically, no claim of the actual start or of the consent of the customer.
|
|
22
|
+
- COSE and Metrological CBOR on ^0.12.0, so that direct and transitive consumers share one codec; existing proof and
|
|
23
|
+
signature fixtures remain valid.
|
|
24
|
+
- `trustPolicyId` is the SHA-256 of the canonical JSON of `{network, holders, minConsensus, urls}`, the URLs as a WHATWG
|
|
25
|
+
URL serializes them without trailing slashes, in their ordinal order, as WWCP_POI3 calculates it
|
|
26
|
+
(`TrustTransition.PolicyIdOf`); in place of their `JSON.stringify`, whose order of properties and escapes are those of
|
|
27
|
+
JavaScript, so that every implementation calculates the same. Every policy identification changes: decisions an app
|
|
28
|
+
keeps under one are made again, and transitions are signed again.
|
|
29
|
+
- A commit is refused without its `json`, `cbor` and `effectiveTree` ETags (SPECIFICATION.md 8.3), as WWCP_POI3 refuses
|
|
30
|
+
it; the epoch change of `tests/vectors/trust-transitions.json` names the ETags of its versions.
|
|
31
|
+
- `trustTransitions.ts` and `documentKeys.ts` with the license header and in the layout of the other sources.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Migration
|
|
35
|
+
|
|
36
|
+
- Commits must name all three version ETags: `json`, `cbor` and `effectiveTree`. A commit accepted by 0.1.1 with
|
|
37
|
+
only an effective-tree ETag is now refused. Producers must generate the complete ETags and sign the resulting commits
|
|
38
|
+
and checkpoints again; do not edit previously signed documents or silently repair an archived original.
|
|
39
|
+
- When moving from the unpublished 0.1.2-dev.0 candidate that used `JSON.stringify` for policy identity, recompute
|
|
40
|
+
`trustPolicyId` from canonical JSON. Reconfirm local decisions under the new identity and regenerate and sign affected
|
|
41
|
+
trust transitions. Retain old observations and original evidence; a changed policy identity must not erase known forks
|
|
42
|
+
or rollbacks. Candidates already using canonical JSON keep their policy identities.
|
|
43
|
+
- COSE and Metrological CBOR both require ^0.12.0. Keep both dependency ranges aligned in consumers that use them directly.
|
|
44
|
+
- The minimum runtime remains Node 22.18, and the package remains ESM-only. Local trust decisions, durable observation
|
|
45
|
+
storage and independently authorized witness policies remain the caller's responsibility. No production trust roots
|
|
46
|
+
or witness service are bundled.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## 0.1.1 (2026-10-31)
|
|
50
|
+
|
|
51
|
+
`TrustContext`, for apps that import a trust anchor before they trust its keys. `TrustContext.evaluate` checks a key
|
|
52
|
+
statement against the identity keys of a trust anchor the app trusts locally and reports its signatures, signers, quorum
|
|
53
|
+
and validity apart (`TrustEvaluation`); a context only when all of them hold, `TrustContext.create` throws otherwise.
|
|
54
|
+
The context keeps the holders of the trust anchor and its quorum, and binds the roaming network, its operator, the
|
|
55
|
+
signed key statement and the time of the evaluation. `OperatorTrust.of` and `fromOperatorJSON`, `verifyVersion`,
|
|
56
|
+
`verifyChargingStation`, `ChargingStationProof.verify` and `verifyCheckpoint` take it in place of a trust anchor; given
|
|
57
|
+
a trust anchor, they verify as before. The app keeps storing and showing its decisions and creates a context from its
|
|
58
|
+
current decisions for every verification. Tested with genuine signatures, the proofs of the conformance tests and in
|
|
59
|
+
Chromium.
|
|
60
|
+
|
|
61
|
+
S31 and S32 of WWCP_POI `d6b0127`. A release keeps its version: a new version is a new release, so that a
|
|
62
|
+
certificate naming a release names the version that was assessed. A change set updating or removing the `version` of a
|
|
63
|
+
transparency software release is refused, and so is one removing a release and adding it again with another version,
|
|
64
|
+
after its last change (`ChangedTransparencySoftwareVersion`; versions compared trimmed and without case, as
|
|
65
|
+
`TransparencySoftwareVersion` compares them). The `notifiedBodyNumber` and `notifiedFor` of a conformity assessment
|
|
66
|
+
body are the roaming network operator's, which vets the body, also once the body has keys: a body issuing a
|
|
67
|
+
certificate under a legislation the same change set adds to its `notifiedFor` signs it together with the operator. A
|
|
68
|
+
number names one body, in every version and after every change set (`DuplicateNotifiedBodyNumber`).
|
|
69
|
+
`tests/releasesAndBodies.test.ts`, after `A_release_keeps_its_version` and
|
|
70
|
+
`The_roaming_network_operator_says_what_a_body_is_notified_for`.
|
|
71
|
+
|
|
72
|
+
A conformity assessment body is refused as its constructor in WWCP_POI refuses it, in its words and order: a
|
|
73
|
+
`notifiedBodyNumber` not of four digits (nothing after them, also no line feed, since WWCP_POI `f53d220`), a legislation
|
|
74
|
+
of `notifiedFor` empty or given twice (with case), a certificate issued under a legislation it is not notified for
|
|
75
|
+
(exactly as written, its certificates in the ordinal order of their identifications), each wrapped as WWCP_POI wraps it,
|
|
76
|
+
e.g. "The given JSON representation of a conformity assessment body is invalid: The certificate 'PTB-2026-0042' is issued
|
|
77
|
+
under the legislation 'CRA', which the conformity assessment body 'PTB' is not notified for! (Parameter 'Certificates')";
|
|
78
|
+
before them a `notifiedBodyNumber` that is no text and a `notifiedFor` that is no array of texts. A version is refused
|
|
79
|
+
for what WWCP_POI refuses of an entity as it reads it before what it refuses of the network made of them, the
|
|
80
|
+
identifications unique within the network last. Checked against WWCP_POI3 itself, on 33 versions of QA: the same, but
|
|
81
|
+
for two refusals of one body at once, a key and its number. In a change set WWCP_POI names the change ("Change 0: …"),
|
|
82
|
+
this library refuses the version it leads to.
|
|
83
|
+
|
|
84
|
+
The four vectors of WWCPPOIConformanceTests `d4a4928` vendored, `poi-refusals.json` of 93 vectors: a key of a party
|
|
85
|
+
whose `notAfter` is written with an offset, as a date only or as null, and one whose key is another CBOR of the same
|
|
86
|
+
COSE key. WWCP_POI refuses them too since `a425530` (D13 there, SPECIFICATION.md 2, Written forms), as this library did;
|
|
87
|
+
the key not in deterministic CBOR now in its words: "Invalid COSE key: Invalid deterministic CBOR: the key of the public
|
|
88
|
+
key '…' is not written as the deterministic CBOR of its COSE key!"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
The four vectors of WWCPPOIConformanceTests `ad7c73e` vendored, `poi-refusals.json` of 97 vectors: a conformity
|
|
92
|
+
assessment body as its constructor in WWCP_POI checks it, a certificate issued under a legislation it is not notified
|
|
93
|
+
for, a notified body number of three digits, a legislation notified for empty, one given twice (D14 there, found against
|
|
94
|
+
`1f914ac`, fixed by `4ff1fc2` here).
|
|
95
|
+
|
|
96
|
+
The legislations a conformity assessment body is notified for are refused unless written in their ordinal order, as
|
|
97
|
+
WWCP_POI writes them (Achim's decision of 2026-10-29, as D13 decided it for keys): WWCP_POI takes another order and
|
|
98
|
+
writes it sorted, which written again would be another text than the one hashed. Refused as the body is read, before
|
|
99
|
+
what its constructor checks, in the words of this library: "The legislations the conformity assessment body 'PTB' is
|
|
100
|
+
notified for are written in their ordinal order!"
|
|
101
|
+
|
|
102
|
+
The four vectors of WWCPPOIConformanceTests `012ce9d` vendored, `poi-refusals.json` of 101 vectors: a conformity
|
|
103
|
+
assessment body as the content holds it, notified for legislations out of their ordinal order, with a notified body
|
|
104
|
+
number that is no text, with a notifiedFor that is no array of texts, and with the number of another body. WWCP_POI
|
|
105
|
+
refuses the order since `8108522`, in the words of this library.
|
|
106
|
+
|
|
107
|
+
WWCP_POI `f53d220`: its regular expressions end with `\z`, no longer with `$`, which in .NET matched before a last line
|
|
108
|
+
feed as well. A notified body number "0102" with a line feed is refused, which this library had taken as WWCP_POI took
|
|
109
|
+
it; a certificate timestamp with a line feed after its offset was refused here already, as every check of this library
|
|
110
|
+
ends at the end of its text.
|
|
111
|
+
|
|
112
|
+
The content as WWCP_POI writes it (SPECIFICATION.md 2, Written forms): what WWCP_POI takes of a version and writes otherwise
|
|
113
|
+
is refused, as written again it would be another text than the one hashed (Achim's decision of 2026-10-29, as D13
|
|
114
|
+
decided it for keys and 9decdb5 for the legislations a body is notified for). Of every entity, `notWrittenAsHeld`, as a
|
|
115
|
+
version is read, after everything WWCP_POI refuses of it, so that its words come first: what the content orders
|
|
116
|
+
(its ordered lists, `POIJSON.OrderedIds`, entities, keys, exchanges) out of its ordinal order, the texts of an ordered list
|
|
117
|
+
untrimmed, a list WWCP_POI writes only with an element given empty (about ninety; not the versions, releases and energy
|
|
118
|
+
meters of a certificate, the elements of a price, the exchanges of a merchant, the identity keys of a key statement), a
|
|
119
|
+
property given as null, an embedded object naming a JSON-LD context, a text in languages not naming each language as
|
|
120
|
+
Styx writes it, in lower case, with a text, a timestamp not UTC to the millisecond; custom data held as given. Of a key of
|
|
121
|
+
a party, a property WWCP_POI does not read; of an EV Taler merchant and its exchanges, such a property, a base URL not as
|
|
122
|
+
Hermod writes it, trimmed and with its scheme, and a currency not by its code. In the words of this library, e.g.
|
|
123
|
+
"'chargingStationOperators[0].chargingPools[1].paymentOptions' is not written as the content holds it: its elements are in the
|
|
124
|
+
order the content holds them in!". The new values of a change set are checked by the same rules (`asGiven`), as
|
|
125
|
+
WWCP_POI refuses a new value the content holds otherwise, "e.g. an empty array written as none". Found by probing
|
|
126
|
+
WWCP_POI3 at 8108522 with 201 versions of QA: of the 20 it takes and writes otherwise this library took all, and
|
|
127
|
+
refuses all now; every one it takes as given is taken, every one it refuses refused, and every version of the frozen run
|
|
128
|
+
is written as the content holds it. `tests/writtenForm.test.ts`.
|
|
129
|
+
|
|
130
|
+
What the constructor of the roaming network refuses, of a version, in the words of WWCP_POI: as an argument of its
|
|
131
|
+
parameter, which its TryParse names, e.g. "The given JSON representation of a roaming network is invalid: The notified
|
|
132
|
+
body number '0102' of the conformity assessment body 'PTB' is the one of the conformity assessment body 'BSI' already!
|
|
133
|
+
(Parameter 'ConformityAssessmentBodies')", in its order (the groups of providers and the offers before the releases): the
|
|
134
|
+
identifications unique within the network, and the key statement and the certificates of the roaming network operator
|
|
135
|
+
(`KeyStatementError`, 'Operator'), its key statement of another network now before its certificates. After the last change
|
|
136
|
+
of a change set they are named bare, in the order WWCP_POI checks them there (`RoamingNetwork.afterChangeSet`). The
|
|
137
|
+
golden vectors held the inner words only. Checked against WWCP_POI3 at 8108522 on 10 versions of QA.
|
|
138
|
+
|
|
139
|
+
The roaming network operator, its key statement and the certificates of its signing keys in the words and order of
|
|
140
|
+
WWCP_POI3 (the TryParse of `RoamingNetworkOperator`, `RoamingNetworkKeyStatement` and
|
|
141
|
+
`RoamingNetworkSigningKeyCertificate`), e.g. "A key statement requires its minConsensus, a whole number from 1 to 255!",
|
|
142
|
+
"Invalid key in the identityKeys of a key statement!", "A signing key certificate requires the signingKey it certifies!";
|
|
143
|
+
what this library refuses besides (properties it does not know, identity keys out of their order) after them. What the
|
|
144
|
+
constructor of the operator refuses as an argument of it, "The given JSON representation of a roaming network operator is
|
|
145
|
+
invalid: …": a certificate by the same identity key given twice, which this library took, a signing key certified in two
|
|
146
|
+
forms, a key both a signing and an identity key, a quorum its keys do not have; the holder of a key as it names it ("the
|
|
147
|
+
holder 'BetaOrg'"). The tree hash algorithms of a roaming network as `POITreeHashAlgorithms` names them, four refusals for
|
|
148
|
+
the one of this library. An entity without its identification as Styx refuses it, "Missing JSON property '@id'!", which
|
|
149
|
+
this library took but of the roaming network and its operator (`invalidIdentification`, first of all), and one of another
|
|
150
|
+
JSON type in the words of the kinds WWCP_POI3 refuses it of ("Invalid 'charging pool identification'!"). Certificates and
|
|
151
|
+
the versions of stations, meters, their templates and models without the prefix this library gave them ("The certificate
|
|
152
|
+
'…': "), as WWCP_POI3 names them, with the parameter its constructor names ("(Parameter 'Versions')", 'HardwareRevisions',
|
|
153
|
+
'FirmwareVersions', 'Legislation', 'NotBefore', 'EnergyMeters'), a version twice in a model as an argument of the model; a
|
|
154
|
+
certificate without its identification, of a certified meter a model of another JSON type, in its words.
|
|
155
|
+
|
|
156
|
+
Of the written form also, as WWCP_POI3 takes and writes it otherwise: an entity without its lastChange, which it writes as
|
|
157
|
+
its created; a party without its name, which it makes up of its kind and identification ("Charging Station Manufacturer
|
|
158
|
+
'GraphDefined'"); a text in languages without a language, but the name of a charging station operator, which it writes
|
|
159
|
+
so; the releases of a certificate and the URLs of an open source license left out, which it writes also empty; the energy
|
|
160
|
+
meters of a certificate given empty; an identification and the type of a charging connector given as a number.
|
|
161
|
+
|
|
162
|
+
Probed against WWCP_POI3 at 8108522 with 617 versions of QA, of every kind of object a property it does not read, every
|
|
163
|
+
property of it removed and given in another JSON type, the tree hash algorithms and the quorum of the operator, and 10
|
|
164
|
+
of certificates and models: none it takes as given is refused here; of what it refuses, this library refuses all in its
|
|
165
|
+
words but 20, of what it takes and writes otherwise all but the properties it does not read (25 kinds, which it leaves
|
|
166
|
+
out). Not ported yet: properties of another JSON type or missing that WWCP_POI3 refuses (168, in the words of every kind)
|
|
167
|
+
and the references it checks (23, of templates, tariffs, members, manufacturers, models, releases and certificates).
|
|
168
|
+
`tests/operator.test.ts`, and in `writtenForm`, `identifications` and `certificates`.
|
|
169
|
+
|
|
170
|
+
The 27 vectors of WWCPPOIConformanceTests `1c36c6d` vendored, `poi-refusals.json` of 128 vectors: versions not written as
|
|
171
|
+
the content holds them (`version-held-*`), the 20 versions WWCP_POI3 at 8108522 took and wrote otherwise and more of their
|
|
172
|
+
kinds (bodies, keys, payment options and exchanges out of their order, an untrimmed payment option, lists given empty, a
|
|
173
|
+
property given as null, embedded JSON-LD contexts, texts in languages not as Styx writes them, a timestamp with an offset,
|
|
174
|
+
properties of keys, merchants and exchanges not read, URLs and currencies not as written), ten with their eTags as
|
|
175
|
+
published, their reasons in the words of this library, which refuses them since `5c534d4`. WWCP_POI refuses them as well
|
|
176
|
+
since D15 of WWCPPOIConformanceTests, fixed there in `1c36c6d` (SPECIFICATION.md 2: a reader MUST refuse a version not
|
|
177
|
+
written so).
|
|
178
|
+
|
|
179
|
+
The written form as WWCP_POI3 refuses it since WWCP_POI `3de830a`, which writes a version again and walks both
|
|
180
|
+
(RoamingNetwork.WrittenForm.cs, FirstNotWritten): `notWritten` walks a version in that order and in those words, the
|
|
181
|
+
reasons of this library, which WWCP_POI took over, and two of its own. "the content leaves it out", of a property given
|
|
182
|
+
that WWCP_POI does not write: of every entity a property its type in WWCP_POI3 neither writes (ToJSON) nor reads
|
|
183
|
+
(PropertyKeys), drawn from it at `3de830a` for 33 kinds and checked against the 605 versions it wrote in the frozen run
|
|
184
|
+
and the probes, of a key statement, its signatures, a certificate of a signing key, a coordinate, a price component and
|
|
185
|
+
a public key of a meter as well; `dataLicenseIds`, which a version names completely (`dataLicenses`), a license it does not know
|
|
186
|
+
in its words; a text in languages without a language WWCP_POI reads. "the content holds it as '…'", of a value it writes
|
|
187
|
+
otherwise, by the path of that value: the lastChange of an entity naming none (its created), the name of a party naming
|
|
188
|
+
none (not of grid and parking operators), the lists it writes also empty, an identification given as a number, texts
|
|
189
|
+
its types write trimmed (identifications, references, currencies, versions, e-mail addresses, URLs), URLs with the
|
|
190
|
+
scheme https, the identification of a charging station operator in upper case, the role of a meter, the legal status of
|
|
191
|
+
a release and signature methods as they are named, coordinates as doubles (50.92710 as 50.9271; quantities keep their
|
|
192
|
+
decimals). Of a release and its licenses, a certificate and the meters it was issued with, a property they do not read
|
|
193
|
+
as WWCP_POI2 refuses it ("Unknown property 'x'."). The roaming network and its operator compared without case and
|
|
194
|
+
trimmed, as their types read them, also of the key statement and the certificates, signed as read. Seven cases keep the
|
|
195
|
+
words of this library, refused where it reads them, before the written form, as WWCP_POI takes them over (Achim's
|
|
196
|
+
decision of 2026-10-30): a property of a key of a party, of an EV Taler merchant or of an exchange, the merchant base URL,
|
|
197
|
+
the base URL and the currency of an exchange not as written. Probed against WWCP_POI3 at `3de830a` with 1257 versions of
|
|
198
|
+
QA: none it takes is refused here; of what it refuses as written otherwise, all in its words but those seven.
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## 0.1.0 (2026-10-29)
|
|
202
|
+
|
|
203
|
+
The first milestone: the examples A1 to A14 of WWCP_POI (commit `33447ac`) checked in TypeScript.
|
|
204
|
+
|
|
205
|
+
The findings of the review this port made of the C# implementation are cited as csharp-review N, N the number of the
|
|
206
|
+
finding in
|
|
207
|
+
[docs/csharp-review.md of WWCPPOIConformanceTests](https://github.com/OpenChargingCloud/WWCPPOIConformanceTests/blob/master/docs/csharp-review.md);
|
|
208
|
+
`docs/` of this repository held it up to `b9c786e`.
|
|
209
|
+
|
|
210
|
+
- Canonical JSON and deterministic CBOR of Styx; a lossless JSON parser keeping decimals as `System.Decimal` holds them.
|
|
211
|
+
- COSE keys, RFC 9679 thumbprints, signatures ES256/384/512, ES256K, ESP*, ESB*, Ed25519, Ed448, ML-DSA-44/65/87.
|
|
212
|
+
- Trust anchors (QR code, URL, JSON), key statements, certificates of signing keys; trust following the key statements
|
|
213
|
+
of a history (`OperatorTrust.followedBy`).
|
|
214
|
+
- Roaming networks with their ETags, effective members and the effective tree; proofs of charging stations, attestations,
|
|
215
|
+
the manufacturers and models of the station and its meters (`manufacturer`, `energyMeterModels`), the transparency
|
|
216
|
+
software and certificates of their energy meters.
|
|
217
|
+
- Change sets with their owners' signatures, commits, linear histories, checkpoints, their proofs and signatures by the
|
|
218
|
+
roaming network operator and by witnesses, archive segments; epochs, their final checkpoints and the genesis of the
|
|
219
|
+
next one.
|
|
220
|
+
- Charging station and energy meter manufacturers, parties stating their models; transparency software manufacturers and
|
|
221
|
+
conformity assessment bodies, parties holding their releases and certificates; the key usages `models`, `software` and
|
|
222
|
+
`certificates`; energy meter templates and groups.
|
|
223
|
+
- Price statements, their chains, checkpoint trees and proofs; evidence of a charging session as the app of example A10
|
|
224
|
+
keeps it (`parseEvidence`).
|
|
225
|
+
- The runtime status: status updates, frames of the WebSocket of a history, the runtime status of a snapshot.
|
|
226
|
+
- `POIClient`: the proof of a charging station and its prices, from the servers of a trust anchor.
|
|
227
|
+
|
|
228
|
+
Moving from the examples at `2d9511d` to `bbd4cbd` also made the ownership of changes the one of the C# implementation
|
|
229
|
+
where the port differed: identity keys of the roaming network operator counted for every change of a party, not only for
|
|
230
|
+
its keys; where it signs in place of a party without keys, its signing keys counted when they may sign `party`, not
|
|
231
|
+
when they may sign the usage of the change (csharp-review 13); its identity and signing keys counted alike for
|
|
232
|
+
everything it owns; and the signing keys of a party could not rotate its signing keys. The values of change sets are
|
|
233
|
+
kept in the order the C# implementation keeps them in (csharp-review 10).
|
|
234
|
+
|
|
235
|
+
Moving on to `801bbce`, the manufacturers became parties: the roaming network operator adds and removes them, they change
|
|
236
|
+
their own properties and state their models with a key that may sign `models`, every change of a model naming its
|
|
237
|
+
manufacturer. A change set changes only the properties of a party the C# implementation lets it change, so that the
|
|
238
|
+
models, releases and certificates of a party are not replaced as one of its properties by a key that may not sign them.
|
|
239
|
+
`forThisModel` of the transparency software of a meter asks for the version of the certificate among the versions of the
|
|
240
|
+
model as well.
|
|
241
|
+
|
|
242
|
+
Node.js 22.18 is the minimum, as of ChargyCore.TS: Node 20 has reached its end of life, and tsup 9, Vitest 5 and
|
|
243
|
+
ESLint 10 do not run on it. The code follows the ESLint rules of ChargyCore.TS; where a missing value used to be asserted
|
|
244
|
+
away, it is refused with a `POIError` saying what is missing. Tests of the bundle as published (its imports, its
|
|
245
|
+
declarations for TypeScript apps, the files `npm pack` takes) and of the library in Chromium join the tests in Node; GitHub
|
|
246
|
+
Actions run all of them on every push, and every night against floating dependencies, the newest codecs of Vanaheimr, and
|
|
247
|
+
the C# examples of WWCP_POI as they are.
|
|
248
|
+
|
|
249
|
+
The test vectors moved to WWCPPOIConformanceTests, which generates golden vectors - canonical JSON and CBOR, encodings,
|
|
250
|
+
the examples of section 6 of the specification, signed station proofs against a trust anchor, the documents of the run of
|
|
251
|
+
the C# examples, and documents to refuse - and runs them against this library and the C# implementation alike. This
|
|
252
|
+
repository vendors them in `tests/vectors` and runs them in `tests/conformance.test.ts`. The nightly check against the C#
|
|
253
|
+
examples of WWCP_POI master moved there as well.
|
|
254
|
+
|
|
255
|
+
The codecs of Vanaheimr are `@vanaheimr/cose` 0.10.0 and `@vanaheimr/metrological-cbor` 0.11.1: `@vanaheimr/cose` 0.9.0
|
|
256
|
+
brought a CBOR codec 0.10 of its own next to the 0.11 this library uses, so that an app installed two copies of it; now
|
|
257
|
+
there is one.
|
|
258
|
+
|
|
259
|
+
The digest of a price statement leaves its signature value out, as WWCP_POI does since `dbf39b0` (SPECIFICATION.md 12.1):
|
|
260
|
+
the SHA-256 of its signature input. The ECDSA twin `(r, n − s)` of a statement, which anybody can make of it, is the same
|
|
261
|
+
statement, of the same digest (csharp-review 2); `PriceStatement.sameSignedContent` is gone. The test vectors
|
|
262
|
+
are those WWCPPOIConformanceTests generates for it, with a new run of the C# examples at `dbf39b0`
|
|
263
|
+
(`tests/vectors/csharp-dbf39b0`).
|
|
264
|
+
|
|
265
|
+
The price statements of an entity are one chain in whichever spelling they name it, as WWCP_POI keys them since
|
|
266
|
+
`4680d99` (SPECIFICATION.md 12.1 to 12.3, `RoamingNetworkHistory.ChainOf`): by its type and its identification without
|
|
267
|
+
`*`, whitespace around it, or case (`priceStatementChainOf`, `PriceStatement.chain`), so that `DE*GEF*E1*1` and
|
|
268
|
+
`DE*GEF*E11` are one EVSE and a split view between them is seen. `follows` compares chains; `verifyPriceStatements`
|
|
269
|
+
refuses a statement naming an entity of the station otherwise than the roaming network does, before its signature is
|
|
270
|
+
looked at; `verifyCheckpointPriceStatements` refuses a checkpoint naming two statements of one entity and sequence with
|
|
271
|
+
different digests, in the order of its tree, both in the words of WWCP_POI. A sequence is at most 2^53 − 1
|
|
272
|
+
(`MAX_PRICE_STATEMENT_SEQUENCE`), as it was read here already. Not ported, as they bound what a server takes: a statement
|
|
273
|
+
more than 1,000,000 beyond the current one of its entity, and the statements a server keeps per operator for its next
|
|
274
|
+
checkpoint. The golden vectors hold both refusals (`tests/vectors/poi-refusals.json`, 75 vectors): the
|
|
275
|
+
statement of example A10 naming its EVSE as `DE*GEF*E11`, checked with the proof of its station
|
|
276
|
+
(`entityPriceStatement`), and checkpoint 4 naming a fourth statement of one sequence, in the other spelling and of
|
|
277
|
+
another price (`checkpointPriceStatements`, its control the checkpoint and its statements as published).
|
|
278
|
+
|
|
279
|
+
The holders of a quorum are counted as the trust anchor names them, as WWCP_POI does since `3e32f48` (SPECIFICATION.md
|
|
280
|
+
4.1, 8.6; csharp-review 1): a trust anchor names the keys per holder, the `@id` of its key or the array of the
|
|
281
|
+
`@id`s of its keys (`TrustAnchor.holders`; in the URL the holders separated by `,`, the keys of one holder by `;`).
|
|
282
|
+
`KeyStatement.verifyHolders` counts the holders as the verifier knows them and refuses a statement naming the trusted
|
|
283
|
+
keys otherwise; a station proof, `OperatorTrust` and the signatures of checkpoints count an attestation or a signature
|
|
284
|
+
for the holder of the trusted identity key that certified its key. A change set naming a key of a party with another
|
|
285
|
+
holder than before is refused.
|
|
286
|
+
|
|
287
|
+
A change set is identified by its content, as WWCP_POI does since `bc3b1bd` (SPECIFICATION.md 4, 5.2;
|
|
288
|
+
csharp-review 4): its `@id` is the SHA-256 of its canonical JSON with its `@context`, without `@id` and
|
|
289
|
+
signatures (`changeSetIdentification`), so that nobody commits another change set in the place of one. `ChangeSet.parse`
|
|
290
|
+
refuses a change set identified otherwise, and one naming change sets in `metadata.rebasedFrom` it was not rebased from;
|
|
291
|
+
`Commit.parse` reads the change set of a commit as well and refuses a commit with one parent whose change set has no
|
|
292
|
+
changes or the identification of a merge. The test vectors are those of a new run of the C# examples at `bc3b1bd`
|
|
293
|
+
(`tests/vectors/csharp-bc3b1bd`).
|
|
294
|
+
|
|
295
|
+
A change set gives its new values as the content holds them, as WWCP_POI requires since `80e4ccc` (SPECIFICATION.md 2,
|
|
296
|
+
4; csharp-review 10): a new value is applied as it is given, no longer written anew as the C# model would, and
|
|
297
|
+
one that names a JSON-LD context in what it embeds (custom data aside, which keeps it), gives identified elements, keys,
|
|
298
|
+
certificates or the lists of section 2 out of their order or twice, or a timestamp not UTC to the millisecond is
|
|
299
|
+
refused. An old value is compared as it is given. The test vectors are those of a new run of the C# examples at
|
|
300
|
+
`80e4ccc` (`tests/vectors/csharp-80e4ccc`).
|
|
301
|
+
|
|
302
|
+
An attestation gives its `validUntil`, at most 24 hours after its `signedAt`, as WWCP_POI requires since `be07037`
|
|
303
|
+
(SPECIFICATION.md 8.5, 8.6, 12.1; csharp-review 7): `Attestation.parse` refuses one without or valid longer
|
|
304
|
+
(`MAX_ATTESTATION_VALIDITY`), so that none is valid forever. The `signedAt` of an attestation or a price statement is the
|
|
305
|
+
choice of its signer: the signing key of an attestation counts when it is valid when it attested and at the time the proof
|
|
306
|
+
is checked, and a price statement is current no longer than its key.
|
|
307
|
+
|
|
308
|
+
A version naming twice an identification WWCP_POI keeps unique within the roaming network is refused, as WWCP_POI refuses
|
|
309
|
+
it (`DuplicateGridConnectionPoint` to `DuplicateEnergyMeterTemplate` of RoamingNetwork.cs): grid connection points, energy
|
|
310
|
+
meters, parking garages, spaces, sensors, space groups, space templates and products, transparency software releases and
|
|
311
|
+
certificates, energy meter templates and groups, the EVSE, charging station and charging pool groups of operators and
|
|
312
|
+
providers, and charging tariff offers, compared as their C# types compare them, without case but parking products, the
|
|
313
|
+
groups by the prefix of their party, `DE-GDF` as `DE*GDF` (`duplicateIdentification`). `RoamingNetwork.parse` checks every
|
|
314
|
+
version it reads, also the one a change set leads to: before, an operator could add a group of the identification a group
|
|
315
|
+
of the provider of its prefix has, and its change set was taken with the after ETags this library calculates. The golden
|
|
316
|
+
vectors `version-twice-*` of WWCPPOIConformanceTests hold both implementations to it, refused in the same words (`reason`).
|
|
317
|
+
|
|
318
|
+
The roaming network operator signs in place of a party without signing keys, e.g. the certificates of a conformity
|
|
319
|
+
assessment body or the grid connection points of a grid operator not taking part, by a signing key that may sign
|
|
320
|
+
`party`, as the examples certify its keys, as WWCP_POI does since `36bb176` (SPECIFICATION.md 4.1; csharp-review 13):
|
|
321
|
+
`checkOwnership` counts its signing keys that may sign `party` besides those that may sign the usage of the change.
|
|
322
|
+
A change set taken before is taken still.
|
|
323
|
+
|
|
324
|
+
A change set naming `rebasedFrom` with a change, but an `Add` or `AddElement`, without `oldValue` is refused, as WWCP_POI
|
|
325
|
+
refuses it since `1717ee2` (SPECIFICATION.md 4; csharp-review 12): only old values tell that a change set
|
|
326
|
+
committed meanwhile changed what it changes, which such a rebase may have overwritten. One not rebased is read as before.
|
|
327
|
+
The golden vector `changeSet-rebased-without-old-value` holds both implementations to it.
|
|
328
|
+
|
|
329
|
+
A model of charging stations or energy meters names its `hardwareRevisions` and `firmwareVersions`, and a charging
|
|
330
|
+
station and an energy meter one `hardwareRevision` and one `firmwareVersion` of it, as WWCP_POI does since `7e0b0ac`
|
|
331
|
+
(csharp-review 16); a certificate (`ConformityCertificate`, the `certificates` of a conformity assessment body)
|
|
332
|
+
is for a model of charging stations or of energy meters, in the hardware revisions and firmware versions it covers, and
|
|
333
|
+
names its components, the transparency software and, of a station model, the energy meters it was issued with; a
|
|
334
|
+
station and a meter name the certificates of their models in `certificateIds`, and the `transparencySoftwareStatus` of
|
|
335
|
+
a meter names a release and its legal status, no certificate, as WWCP_POI does since `987fa26` (csharp-review 17).
|
|
336
|
+
Change sets change them, effective members take them of their templates, and a certificate is unique within the
|
|
337
|
+
network. `verifyChargingStation` gives the `certificates` the station and its meters name, each with `forThisModel`:
|
|
338
|
+
whether it is for the model, the hardware revision and the firmware version of what names it; the `transparencySoftware`
|
|
339
|
+
of a meter gives the certificates naming its release, no longer a certificate of its own. The test vectors are those of
|
|
340
|
+
a new run of the C# examples at `987fa26` (`tests/vectors/csharp-987fa26`).
|
|
341
|
+
|
|
342
|
+
A charging station signing measurements itself names its `serialNumber`, `transparencySoftwareStatus`,
|
|
343
|
+
`signatureMethods` and `publicKeys` as an energy meter does, and the `modelURL` of its model; an EVSE names its
|
|
344
|
+
`iso15118Certificate`, as WWCP_POI does since `52f1172`. Change sets change them; an effective station takes the model
|
|
345
|
+
URL, the releases and the signature methods of its templates besides its own, never the serial number, the public keys
|
|
346
|
+
or the ISO 15118 certificate of the single device; and a change set giving the releases of a station or a meter out of
|
|
347
|
+
the order of their identifications, or one twice, is refused. `verifyChargingStation` gives the releases the station
|
|
348
|
+
names among its `transparencySoftware`, proven by the certificates of the station; each entry names what names it,
|
|
349
|
+
`namedBy` as of a certificate, in place of `energyMeterId` (`NamedTransparencySoftware` in place of
|
|
350
|
+
`MeterTransparencySoftware`). The test vectors stay those of the run at `987fa26`: no station of its examples signs
|
|
351
|
+
measurements itself.
|
|
352
|
+
|
|
353
|
+
The first checkpoint of an epoch takes signatures of the algorithms of its epoch and of the epoch before, no other, as
|
|
354
|
+
WWCP_POI does since `65e658d` (SPECIFICATION.md 11.3; csharp-review 14): a history started by
|
|
355
|
+
`startNextEpoch` knows the profiles of the epoch it closed, one started from a snapshot those its `epoch` names as
|
|
356
|
+
`previousProfiles` (`History.previousEpochProfiles`), and those of the first epoch are the default ones; without them
|
|
357
|
+
it takes the algorithms of its own epoch alone. A snapshot of the epoch 2 naming profiles of the epoch before is refused.
|
|
358
|
+
|
|
359
|
+
A certificate the roaming network operator adds or changes in place of a conformity assessment body without signing keys
|
|
360
|
+
says so, `"statedBy": "roamingNetworkOperator"`, as WWCP_POI requires since `65e658d` (SPECIFICATION.md 4.1;
|
|
361
|
+
csharp-review 15): a change set adding or changing a certificate whose `statedBy` does not say who signs it, as
|
|
362
|
+
the version before has the keys of the body, is refused. `verifyChargingStation` gives each certificate with `statedBy`,
|
|
363
|
+
`ConformityAssessmentBody` or `RoamingNetworkOperator`, in place of `bodyHasKeys`, which could not tell them apart once
|
|
364
|
+
the body had keys. The test vectors stay those of the run at `987fa26`: none of its examples has a third epoch or a
|
|
365
|
+
certificate stated in place of a body.
|
|
366
|
+
|
|
367
|
+
A version naming a hardware revision, firmware version or serial number WWCP_POI refuses is refused, read or led to by a
|
|
368
|
+
change set, as WWCP_POI reads them since `c31e5e3` and `3672b06` (`HardwareRevision`, `FirmwareVersion`,
|
|
369
|
+
`SerialNumber`): a text as it is given, not empty and neither beginning nor ending with whitespace as `Char.IsWhiteSpace`
|
|
370
|
+
tells it, of charging stations, energy meters and their templates, of the models of their manufacturers, and of
|
|
371
|
+
certificates and the energy meters they were issued with, each once in a model, a certificate and such an energy meter
|
|
372
|
+
(`ModelVersions.Of`), in the words of WWCP_POI (`invalidVersionText`, which `RoamingNetwork.parse` checks with
|
|
373
|
+
`duplicateIdentification`, and for certificates `invalidCertificates`, below). Whether one is of the model of what names
|
|
374
|
+
it stays with the references, which this library
|
|
375
|
+
leaves to WWCP_POI. The test vectors stay those of the run at `987fa26`, whose versions name none it refuses; the vectors
|
|
376
|
+
`version-text-*` of WWCPPOIConformanceTests, its head so changed, hold both implementations to it, refused in the same
|
|
377
|
+
words (`reason`).
|
|
378
|
+
|
|
379
|
+
The golden vectors of WWCPPOIConformanceTests hold, besides the run of the C# examples, small histories it signs itself
|
|
380
|
+
(`tests/vectors/poi-histories.json`), replayed step by step in `tests/conformance.test.ts`: who signs in place of a
|
|
381
|
+
party without keys, who states a certificate, old values and rebases, keys expired and removed, new values as the
|
|
382
|
+
content holds them, `lastChange` of what embeds a change, and three epochs (csharp-review 3, 8, 10, 12 to 15). Ten of
|
|
383
|
+
them - the references a version holds, the groups of e-mobility providers, grid connection points - this library
|
|
384
|
+
leaves to WWCP_POI, and does not run. They found a deviation of this library (D8 of WWCPPOIConformanceTests): a change
|
|
385
|
+
set signed, besides by its owner, by a key of a party not valid at its `createdAt` was taken here, and refused by
|
|
386
|
+
WWCP_POI. Every signature by a key of a party of the version is now by one valid at the `createdAt` of the change set,
|
|
387
|
+
also one besides the signatures of the owners, refused otherwise in the words of WWCP_POI (`TryGetSigners`); only a new
|
|
388
|
+
identity key, which proves its possession, may be one valid later (SPECIFICATION.md 4.1).
|
|
389
|
+
|
|
390
|
+
A version naming a certificate WWCP_POI refuses to read is refused, read or led to by a change set, as
|
|
391
|
+
`ConformityCertificate` and `CertifiedEnergyMeter` of WWCP_POI read them (`src/network/certificates.ts`,
|
|
392
|
+
`invalidCertificates`, which `RoamingNetwork.parse` checks after `invalidVersionText`): for exactly one model, with its
|
|
393
|
+
manufacturer; at least one hardware revision and one firmware version, also of each energy meter it was issued with, as
|
|
394
|
+
an object of its manufacturer and its model; an absolute `documentURL`, a legislation not empty, timestamps with an
|
|
395
|
+
explicit offset, `notBefore` not after `notAfter` to the tick; at least one release, each once (compared ordinally once
|
|
396
|
+
trimmed, as WWCP_POI does), none both verified and compatible (compared without case); energy meters of a charging
|
|
397
|
+
station model only, each model once, compared without case. Refused in the words and in the order of WWCP_POI: first
|
|
398
|
+
what it reads as the arguments of a certificate, by their path, then what its constructor checks. Its versions as
|
|
399
|
+
texts moved there from `invalidVersionText`, in the same words. The vectors `version-certificate-*` of
|
|
400
|
+
WWCPPOIConformanceTests found that this library took all of them (D9) and hold both implementations to it. Whether a
|
|
401
|
+
certificate's model, versions, releases and legislation are those of the network stays with the references, which this
|
|
402
|
+
library leaves to WWCP_POI; an unknown property, also of a certificate, this library does not refuse.
|
|
403
|
+
|
|
404
|
+
A history starts from a snapshot of another server only anchored in the trust anchor of the roaming network, fail
|
|
405
|
+
closed, as a peer of WWCP_POI starts since `ff2c56f` (SPECIFICATION.md 10.5, *Anchored*; `History.fromSnapshot` with
|
|
406
|
+
`SnapshotOptions`): a snapshot of a checkpoint by the checkpoint, signed in the role of the roaming network operator by
|
|
407
|
+
signing keys of as many holders as the trust anchor and the key statement of its version require, each certified by a
|
|
408
|
+
trusted identity key of its holder, valid when it signed and at `at` (`ChargingStationProof.verifyCheckpoint`, as
|
|
409
|
+
`Verify(Checkpoint, TrustAnchor)` of WWCP_POI); a snapshot of the head by the `attestations` it carries since then (8.5),
|
|
410
|
+
which must attest the root of its head as for a proof of the root (`ChargingStationProof.ofRoot`, as `VerifyHead` of
|
|
411
|
+
WWCP_POI). Without a trust anchor no snapshot is taken, unless the caller takes it `unanchored` explicitly, e.g. a genesis
|
|
412
|
+
whose key statement it verifies against the trust anchor itself; an archive segment replays its base so, anchored by the
|
|
413
|
+
checkpoint of its end. Before, a snapshot of the head carrying attestations was refused, and every snapshot taken
|
|
414
|
+
unanchored. An attestation of a snapshot that cannot be read is refused, not left out.
|
|
415
|
+
|
|
416
|
+
A signed commit or checkpoint, also the commit of a snapshot, is refused without a verifier of its signatures, as
|
|
417
|
+
WWCP_POI does (`CheckSignatures`): before, its signatures were taken unchecked when `HistoryOptions.verifyCommit` or
|
|
418
|
+
`verifyCheckpoint` was left out (O3 of WWCPPOIConformanceTests). `verifyCommit` checks the commit of a snapshot as well,
|
|
419
|
+
its version before unknown there (`before` undefined).
|
|
420
|
+
|
|
421
|
+
QI-Digital documents, the proof of concept of WWCP_POI (`WWCP_POI3/RoamingNetwork/QIDigital`, as of `6a0f96e`, which
|
|
422
|
+
example A14 uses), are read and checked, not signed (`src/qidigital/`): the digital calibration certificate of a charging
|
|
423
|
+
station or an energy meter (`DigitalCalibrationCertificate`), the digital certificate of conformity of a model or, of a
|
|
424
|
+
module of quality assurance, of the quality system of a manufacturer (`DigitalCertificateOfConformity`), and the digital
|
|
425
|
+
declaration of conformity of a model (`DigitalDeclarationOfConformity`). Each is refused in the words and the order of
|
|
426
|
+
WWCP_POI: only its own properties, its context, timestamps exactly as signed, numbers as numbers, what its constructor
|
|
427
|
+
checks after its properties were read. Its signature input and its digest are what WWCP_POI writes again of what it read
|
|
428
|
+
(`Content()`), not the text as given: numbers without trailing zeros, a whole one as an integer, identifications trimmed,
|
|
429
|
+
a charging station as `DE*GEF*S1`, `mainSigner` false, an empty list or text and a revision 0 as WWCP_POI writes them.
|
|
430
|
+
Checked against a roaming network as WWCP_POI checks them: the issuer a party of it, its key one that may sign the
|
|
431
|
+
document and valid when it signed and at `at`; the notified body with its number, notified for the legislation; the
|
|
432
|
+
model, its manufacturer, revisions and versions; the charging station or energy meter of a calibration certificate as it
|
|
433
|
+
is at runtime, with what its templates give it, and with the serial number the roaming network gives it, not the one the
|
|
434
|
+
certificate names (csharp-review 23). And against each other: a declaration and each certificate it names, a certificate
|
|
435
|
+
and the item of a calibration certificate it covers. A text in languages of no language, one that is no text and a
|
|
436
|
+
language given twice are refused, not left out, as WWCP_POI refuses them since `bbe8fb8`: left out, they would travel
|
|
437
|
+
unsigned with a signed document.
|
|
438
|
+
A URL is read as Hermod reads it as far as a document URL needs it: trimmed, https unless it names a scheme, of http or
|
|
439
|
+
https with a host.
|
|
440
|
+
|
|
441
|
+
The test vectors are those of a new run of the C# examples at `33447ac` (`tests/vectors/csharp-33447ac`), the first with
|
|
442
|
+
example A14: the QI-Digital documents of the meter of DE*GEF*E2*1 as WWCP_POI signed them, with ML-DSA-65 by the PTB and
|
|
443
|
+
EM-LAB and with ES256 by SAALE, are checked against QA as example A14 published it, refused changed in the words of
|
|
444
|
+
WWCP_POI, and written again as WWCP_POI wrote them. EM-LAB is a member of QA since, so the head is revision 8 of epoch 2.
|
|
445
|
+
`examples/validate-examples.ts` checks example A14 as its `Validate()` does, and starts from the snapshots of examples A4,
|
|
446
|
+
A5 and A11 anchored in the trust anchor, from the genesis and the live snapshot of example A12 unanchored, as the
|
|
447
|
+
examples do: since the anchored start it refused them.
|
|
448
|
+
|
|
449
|
+
The golden vectors hold the QI-Digital documents of example A14 too (`tests/vectors/poi-qidigital.json`), run in
|
|
450
|
+
`tests/conformance.test.ts` as WWCPPOIConformanceTests runs them against WWCP_POI: the four documents verified against
|
|
451
|
+
QA, the declaration of conformity against the certificates it names, both certificates covering the meter of
|
|
452
|
+
DE*GEF*E2*1, a calibration certificate of the charging station DE*GEF*S2, signed by the generator with a key QA patched
|
|
453
|
+
gives EM-LAB, and 38 refusals, each with its control, of documents or of QA patched. Both implementations refuse a text
|
|
454
|
+
of no language, or one that is no text (D10 there, fixed in WWCP_POI `bbe8fb8`), and the calibration certificate of a
|
|
455
|
+
station against one of another serial number, or of none (csharp-review 23).
|
|
456
|
+
|
|
457
|
+
EV Taler, phase 1 of the concept of WWCP_POI for paying for charging with GNU Taler (`concepts/EVTaler.md`), as of
|
|
458
|
+
`ec3dace`: a charging station operator names its merchant at a GNU Taler merchant backend and the exchanges whose coins it
|
|
459
|
+
accepts (`evTaler`, `evTalerMerchantOf`), refused where WWCP_POI refuses it and in its words: base URLs of HTTPS without
|
|
460
|
+
user, query and fragment, ending in '/', read as Hermod reads them; keys as GNU Taler writes them (`isTalerPublicKey`);
|
|
461
|
+
at least one exchange, each once, of an ISO 4217 currency of Styx and with a name. A change of it needs a signing key
|
|
462
|
+
that may sign the new usage `payments`. Payment options are an open set of names: any nonempty text, none twice whatever
|
|
463
|
+
its case, united with those of the templates of a charging pool without case; a charging pool or template naming EVTaler
|
|
464
|
+
needs the merchant of its operator, after the last change of a change set. An app reads the EV Taler tariff of an EVSE
|
|
465
|
+
and the exchanges in its currency from the proof of its station (`evTalerTariffOf`, `evTalerExchangesAt`), and what
|
|
466
|
+
drivers see, "EV Taler (Example Exchange, EUR)" (`paymentOptionName`). The JSON, the CBOR and the tree of a version with
|
|
467
|
+
a merchant are those WWCP_POI writes: `tests/evTaler.test.ts` holds the ETags WWCP_POI3 calculates of QA with the merchant
|
|
468
|
+
of its EVTalerTests. Not yet: golden vectors of WWCPPOIConformanceTests, and a station proof with a merchant as WWCP_POI
|
|
469
|
+
signs it (example A15 came after the frozen run). Nothing here takes or makes a payment.
|
|
470
|
+
|
|
471
|
+
The keys of the parties of a roaming network are read where it is read, as WWCP_POI reads them wherever it reads a
|
|
472
|
+
party (`POIPartyKeys.TryParse` and `Check`), in its words (D12 of WWCPPOIConformanceTests): before, a party's keys were
|
|
473
|
+
only read where they were used, so a version naming an unknown usage of a party's key was taken. Every key as
|
|
474
|
+
`POIPublicKey.parse` reads it, none twice, none both a signing and an identity key, no identity key naming usages; the
|
|
475
|
+
parties in the order WWCP_POI reads them, the charging station operators last; the identity keys of the roaming network
|
|
476
|
+
operator in the same words (`src/network/partyKeys.ts`). Checked against WWCP_POI3 at `ec3dace` itself, on 47 versions
|
|
477
|
+
of QA with keys valid and not, of every kind of party: 40 are read as WWCP_POI3 reads them, in the same words; 5 both
|
|
478
|
+
refuse, in other words of `POIPublicKey.parse` within the same wrapper (a key without identification or key, not
|
|
479
|
+
Base64, expiring before it becomes valid, of another JSON-LD context); 2 name a `notAfter` WWCP_POI takes and writes
|
|
480
|
+
otherwise (a date only, an offset), refused here as every timestamp not written as POI writes it. `poi-refusals.json` of
|
|
481
|
+
WWCPPOIConformanceTests vendored, 89 vectors: the 13 of EV Taler and `version-key-usage-unknown`, D12 closed.
|
|
482
|
+
|
|
483
|
+
A key is read in the words and order of `POIPublicKey.TryParse` of WWCP_POI (`POIPublicKey.parse`): its identification
|
|
484
|
+
and key as texts, then its JSON-LD context, then both given ("A public key needs its identification and its key!"); a
|
|
485
|
+
key .NET can not read as Base64 in the words of .NET, one it reads but writes otherwise as not canonical; "Invalid COSE
|
|
486
|
+
key: …", "A public key must not contain private parts!", "The holder of a public key must be a text!"; a key expiring
|
|
487
|
+
before it becomes valid where the constructor of WWCP_POI refuses it, after its holder and usages, before its
|
|
488
|
+
thumbprint. Checked against WWCP_POI3 at `ec3dace` itself, on 45 more versions of QA with keys valid and not: 34 in its
|
|
489
|
+
words. Still other words: a key of CBOR WWCP_POI3 can not read (the words of `@vanaheimr/cose` and
|
|
490
|
+
`@vanaheimr/metrological-cbor`, not of their C# originals), a timestamp both refuse ("Invalid value for 'not before'!"
|
|
491
|
+
there). Refused here, taken and written otherwise by WWCP_POI3: a key not in deterministic CBOR, a timestamp not written
|
|
492
|
+
as POI writes it, a `notBefore` or `notAfter` of null.
|
|
493
|
+
|
|
494
|
+
`poi-histories.json` of WWCPPOIConformanceTests `0734641` vendored: 8 replays of EV Taler in a history the generator
|
|
495
|
+
signs, who may sign the merchant of DE*GEF (a signing key for `payments`; the roaming network operator only in place
|
|
496
|
+
of a party without signing keys) and a charging pool naming EVTaler with and without it. A change needing signatures is
|
|
497
|
+
named as WWCP_POI names it, with the property it changes, e.g. "Change 0: UpdateProperty of the
|
|
498
|
+
ChargingStationOperator 'DE*GEF' ('evTaler') needs a signature by …".
|