@open-charging-cloud/wwcp-poi 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +382 -0
  2. package/README.md +534 -362
  3. package/dist/crypto/ber.d.ts +48 -0
  4. package/dist/crypto/ber.d.ts.map +1 -0
  5. package/dist/crypto/certificates.d.ts +21 -0
  6. package/dist/crypto/certificates.d.ts.map +1 -0
  7. package/dist/crypto/curves.d.ts +25 -0
  8. package/dist/crypto/curves.d.ts.map +1 -0
  9. package/dist/crypto/ecc.d.ts +34 -0
  10. package/dist/crypto/ecc.d.ts.map +1 -0
  11. package/dist/crypto/publicKeys.d.ts +51 -0
  12. package/dist/crypto/publicKeys.d.ts.map +1 -0
  13. package/dist/crypto/rsa.d.ts +30 -0
  14. package/dist/crypto/rsa.d.ts.map +1 -0
  15. package/dist/encoding/text.d.ts +9 -0
  16. package/dist/encoding/text.d.ts.map +1 -1
  17. package/dist/evTaler/amounts.d.ts +89 -0
  18. package/dist/evTaler/amounts.d.ts.map +1 -0
  19. package/dist/evTaler/contractTerms.d.ts +107 -0
  20. package/dist/evTaler/contractTerms.d.ts.map +1 -0
  21. package/dist/evTaler/meterValue.d.ts +65 -0
  22. package/dist/evTaler/meterValue.d.ts.map +1 -0
  23. package/dist/evTaler/payURI.d.ts +28 -0
  24. package/dist/evTaler/payURI.d.ts.map +1 -0
  25. package/dist/evTaler/settlement.d.ts +85 -0
  26. package/dist/evTaler/settlement.d.ts.map +1 -0
  27. package/dist/evTaler/step.d.ts +72 -0
  28. package/dist/evTaler/step.d.ts.map +1 -0
  29. package/dist/history/apply.d.ts +6 -1
  30. package/dist/history/apply.d.ts.map +1 -1
  31. package/dist/history/changeSet.d.ts +18 -2
  32. package/dist/history/changeSet.d.ts.map +1 -1
  33. package/dist/history/checkpoint.d.ts +7 -0
  34. package/dist/history/checkpoint.d.ts.map +1 -1
  35. package/dist/history/commit.d.ts +13 -1
  36. package/dist/history/commit.d.ts.map +1 -1
  37. package/dist/history/elements.d.ts +19 -0
  38. package/dist/history/elements.d.ts.map +1 -0
  39. package/dist/history/epoch.d.ts +2 -0
  40. package/dist/history/epoch.d.ts.map +1 -1
  41. package/dist/history/history.d.ts +46 -6
  42. package/dist/history/history.d.ts.map +1 -1
  43. package/dist/history/preconditions.d.ts +22 -0
  44. package/dist/history/preconditions.d.ts.map +1 -0
  45. package/dist/index.d.ts +18 -4
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +10296 -1558
  48. package/dist/index.js.map +1 -1
  49. package/dist/json/canonical.d.ts.map +1 -1
  50. package/dist/keys.d.ts +2 -0
  51. package/dist/keys.d.ts.map +1 -1
  52. package/dist/network/certificates.d.ts +16 -4
  53. package/dist/network/certificates.d.ts.map +1 -1
  54. package/dist/network/countries.d.ts +16 -0
  55. package/dist/network/countries.d.ts.map +1 -0
  56. package/dist/network/evTaler.d.ts +1 -14
  57. package/dist/network/evTaler.d.ts.map +1 -1
  58. package/dist/network/identifications.d.ts +6 -6
  59. package/dist/network/identifications.d.ts.map +1 -1
  60. package/dist/network/measurementPublicKey.d.ts +7 -0
  61. package/dist/network/measurementPublicKey.d.ts.map +1 -0
  62. package/dist/network/offers.d.ts +53 -0
  63. package/dist/network/offers.d.ts.map +1 -0
  64. package/dist/network/partyKeys.d.ts +8 -5
  65. package/dist/network/partyKeys.d.ts.map +1 -1
  66. package/dist/network/poiJSON.d.ts +172 -0
  67. package/dist/network/poiJSON.d.ts.map +1 -0
  68. package/dist/network/poiValues.d.ts +48 -0
  69. package/dist/network/poiValues.d.ts.map +1 -0
  70. package/dist/network/reading.d.ts +46 -0
  71. package/dist/network/reading.d.ts.map +1 -0
  72. package/dist/network/references.d.ts +36 -0
  73. package/dist/network/references.d.ts.map +1 -0
  74. package/dist/network/roamingNetwork.d.ts +10 -11
  75. package/dist/network/roamingNetwork.d.ts.map +1 -1
  76. package/dist/network/timeZones.d.ts +8 -0
  77. package/dist/network/timeZones.d.ts.map +1 -0
  78. package/dist/network/tree.d.ts +14 -0
  79. package/dist/network/tree.d.ts.map +1 -1
  80. package/dist/network/versionTexts.d.ts +1 -7
  81. package/dist/network/versionTexts.d.ts.map +1 -1
  82. package/dist/network/writtenForm.d.ts.map +1 -1
  83. package/dist/proofs/priceStatement.d.ts.map +1 -1
  84. package/dist/proofs/stationProof.d.ts +2 -0
  85. package/dist/proofs/stationProof.d.ts.map +1 -1
  86. package/dist/proofs/trustContext.d.ts +6 -0
  87. package/dist/proofs/trustContext.d.ts.map +1 -1
  88. package/dist/verifier/chargingStation.d.ts +5 -0
  89. package/dist/verifier/chargingStation.d.ts.map +1 -1
  90. package/dist/verifier/checkpoints.d.ts +6 -0
  91. package/dist/verifier/checkpoints.d.ts.map +1 -1
  92. package/dist/verifier/documentKeys.d.ts +27 -0
  93. package/dist/verifier/documentKeys.d.ts.map +1 -0
  94. package/dist/verifier/historicalMeasurements.d.ts +96 -0
  95. package/dist/verifier/historicalMeasurements.d.ts.map +1 -0
  96. package/dist/verifier/measurementKeys.d.ts +48 -0
  97. package/dist/verifier/measurementKeys.d.ts.map +1 -0
  98. package/dist/verifier/observedVersions.d.ts +70 -0
  99. package/dist/verifier/observedVersions.d.ts.map +1 -0
  100. package/dist/verifier/pricePublication.d.ts +74 -0
  101. package/dist/verifier/pricePublication.d.ts.map +1 -0
  102. package/dist/verifier/sessionPrices.d.ts +75 -0
  103. package/dist/verifier/sessionPrices.d.ts.map +1 -0
  104. package/dist/verifier/trustTransitions.d.ts +67 -0
  105. package/dist/verifier/trustTransitions.d.ts.map +1 -0
  106. package/package.json +15 -14
package/CHANGELOG.md CHANGED
@@ -2,6 +2,388 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+
6
+ ## 0.3.0 (prepared; not yet published)
7
+
8
+ WWCP_POI3 as the measure: a roaming network is read as WWCP_POI3 reads it and refused in its words, change sets apply
9
+ what WWCP_POI3 applies (the entities a party embeds, element changes, preconditions, no lastChange going back),
10
+ histories require the signature roles WWCP_POI requires and take a checkpoint with the signatures that verify, and EV
11
+ Taler phase 2 checks the steps and the settlement of a session. Each of them is probed against WWCP_POI3, what differs
12
+ named below, and the vectors of WWCPPOIConformanceTests `215023a` hold, none deviating. See [Migration](#migration)
13
+ before upgrading: versions, change sets and signatures 0.2.0 took are refused, and the types of three properties change.
14
+
15
+ - A roaming network is read as WWCP_POI3 reads it (`RoamingNetwork.TryParse` and the TryParse of every entity) and
16
+ refused in its words and its order: JSON types, mandatory properties, values, identifications, names of enumerations,
17
+ currencies, URLs, timestamps, texts in languages, data licenses, and what the constructor of each entity refuses of
18
+ what it read (`src/network/reading.ts`, `poiJSON.ts`, `poiValues.ts`). Every kind of entity it reads: the roaming
19
+ network and its operator; charging station operators with their pools, stations, EVSEs, connectors, energy meters,
20
+ templates, groups, tariffs, tariff templates, groups and offers, brands and parking spaces; manufacturers of charging
21
+ stations and energy meters with their models, transparency software manufacturers with their releases, conformity
22
+ assessment bodies, e-mobility providers, grid operators with their grid connection points, parking operators.
23
+ - The references the constructor of the roaming network checks, and the identifications it keeps unique among them,
24
+ interleaved in its order (`references.ts`): manufacturers, models, hardware revisions and firmware versions, releases,
25
+ certificates, grid connection points, charging stations, parking spaces and maintainers the network does not have, a
26
+ station or an energy meter contradicting its model, a key of two parties. After the last change of a change set, bare,
27
+ in the order of `RoamingNetwork.ChangeSets.cs`, a reference the version before resolves named as one the change set
28
+ withdrew. They replace the separate checks of identifications, versions, certificates, EV Taler and keys of parties.
29
+ - 1268 versions probed against WWCP_POI3 at 89d2e02 are taken and refused alike, in the same words, but for nine agreed:
30
+ five identifications of the roaming network and its operator given as numbers, which keep the words of this library
31
+ for WWCP_POI3 to take, and four messages of the CBOR and COSE libraries.
32
+ - Values WWCP_POI3 writes otherwise than given are refused in the words of its written form (`writtenForm.ts`): a
33
+ number, a boolean or a text given as another JSON type it reads it of (`"0.390"` as 0.390, `"TRUE"` as true, 5 as
34
+ `"5"`), coordinates of texts and booleans, durations in seconds in whole ticks of 100 ns without trailing zeros (1.50
35
+ as 1.5), the width and height of an image; opening times as Styx writes them, `24/7` always, hours `HH:mm`, periods
36
+ UTC, empty lists and free texts left out; NUTS codes in upper case, a list written otherwise compared element by
37
+ element with the one WWCP_POI3 writes; addresses with their countries by their alpha-3 codes, their street, postal
38
+ code and time zone trimmed, their other texts as given and left out where empty, their languages in lower case,
39
+ nothing else. A country is read as `Country.TryParse` of Styx reads it, of its 251 countries (`countries.ts`): by its
40
+ alpha-2 or alpha-3 code in any case, its numeric code, its calling code or one of its names, and refused where it
41
+ names none. Of 164 more versions probed against WWCP_POI3 at 89d2e02, 163 are taken and refused alike, in the same
42
+ words; the one left gives a number with an exponent, which the probe writes otherwise before WWCP_POI3 reads it.
43
+ - Two charging tariff offers of an operator must not overlap (`offers.ts`, `OverlappingOffers` of WWCP_POI3, SPECIFICATION.md
44
+ 9.4): covering one EVSE, for some of the same sessions (ad hoc, or contracts of a provider both name, or one names
45
+ none), at some of the same times within their `notBefore` and `notAfter`, both inclusive, and their opening times in the
46
+ time zone of the EVSE's charging pool, with what its templates give it, else UTC; local times as `TimeZoneInfo`
47
+ converts them, one a change to daylight saving time skips the first after it, one it gives twice the one of standard
48
+ time; exceptional closings
49
+ close, exceptional openings open. Refused in its words, at the first EVSE in the ordinal order, as the constructor of
50
+ the operator refuses it, also after a change set. After a change set also two offers of an e-mobility provider the
51
+ change set changed that overlap and did not in the version before (`NewProviderOfferOverlap`); by the changes of
52
+ others they may. Of 64 versions probed against WWCP_POI3 at d1c41ca, all are taken and refused alike, in the same
53
+ words, also those of time zones a charging pool may not name.
54
+ - The time zone of a charging pool or a charging pool template is one of a region of the IANA time zone database, as
55
+ the database writes it, which this platform knows (`timeZones.ts`, `POITimeZones` of WWCP_POI3 `d1c41ca`,
56
+ SPECIFICATION.md 9.4, D17 of the conformance tests): `Europe/Berlin`, also an older name the database keeps for one,
57
+ `Asia/Kolkata` as `Asia/Calcutta`, or of a part of a region, `America/Argentina/Buenos_Aires`. No name of another
58
+ system (`W. Europe Standard Time`), none without a region (`CET`, `UTC`, `Etc/GMT-1`, `US/Eastern`), none in another
59
+ case (`europe/berlin`), none the platform does not know: refused in the words of WWCP_POI3 as the constructor of the
60
+ pool or template refuses it, trimmed, after its images, no longer taken as UTC, nor a Windows name as its IANA name.
61
+ The case is the one Temporal gives (Node 26); without Temporal (Node 22 and 24) Intl gives it of a name, but of an
62
+ older name only the name it stands for, so an older name is then taken in any case (`Asia/KOLKATA`). Of 92 versions
63
+ probed against WWCP_POI3 at `d1c41ca`, 90 are taken and refused alike, in the same words; the two left name
64
+ `America/Ciudad_Juarez` and `Antarctica/Troll`, which .NET on Windows does not find, and this library takes, as Node
65
+ knows them: databases of different age know different names (SPECIFICATION.md 9.4). `poi-refusals.json` of
66
+ WWCPPOIConformanceTests vendored again without the marker of D17: its 10 time zones are refused by their reasons.
67
+ - A measurement public key is a key as BouncyCastle 2.7.0 makes one, as WWCP_POI3 checks it (`measurementPublicKey.ts`,
68
+ `MeasurementPublicKey.TryCheck`), refused in its words and those of BouncyCastle: a SubjectPublicKeyInfo of DER
69
+ (`ber.ts`), of RSA, also of PSS and OAEP, its modulus odd, of no prime factor up to 743, of 16384 bits at most and no
70
+ prime, its exponent odd (`rsa.ts`); of EC on the 84 named curves BouncyCastle knows (`curves.ts`, taken from it), a point
71
+ it decodes, compressed, uncompressed or hybrid, on its curve and of its order (`ecc.ts`); of Ed25519 and Ed448 a point
72
+ of no small order; of X25519, X448, ML-DSA, ML-KEM and SLH-DSA of their lengths; of DSA in its group. Its certificates
73
+ DER, as X509CertificateParser reads them, the first of the key, each one issued by the next one, its signature of
74
+ ECDSA, DSA, RSA of PKCS #1 v1.5 or PSS, Ed25519, Ed448 or ML-DSA verified with the key of the next one
75
+ (`certificates.ts`). Of 242 keys and chains of BouncyCastle and variants of them probed against WWCP_POI3 at 89d2e02,
76
+ 237 are taken and refused alike, in the same words; taken as given, where WWCP_POI3 checks them: points on curves over
77
+ binary fields, explicit curve parameters, keys of Diffie-Hellman, ElGamal, GOST and DSTU. Not verified, so refused: a
78
+ certificate signed with GOST, SM2 or SLH-DSA.
79
+ - Other words: decimals in messages invariant and line breaks `\n`, where WWCP_POI3 writes them in the culture of its
80
+ machine and `\r\n`; timestamps `DateTimeOffset` reads and the written form refuses, refused as invalid; an error of an
81
+ entity changed by a change set without the `Change N:` of WWCP_POI3.
82
+ - A price statement reads its price status as WWCP_POI3 reads it (`ChargingPrices.TryParse`), in its words and order,
83
+ under its "Invalid price status of the price statement:": the prices of each charging tariff once, the tariff named
84
+ by its identification `{operatorId}*T{suffix}` (SPECIFICATION.md 2, 12.1, D16 of the conformance tests), their
85
+ elements, at least one, as a tariff has them, no property or JSON-LD context besides. A statement naming another text
86
+ is no price statement: the price evidence of a session holding one has invalid signatures, as WWCP_POI3 gives it
87
+ (`sessionPrice-foreign-tariff`), not valid ones of a tariff outside the references of its EVSE.
88
+ - The nine vectors of WWCPPOIConformanceTests `fde40c9` vendored, `poi-refusals.json` of 129 vectors (a version naming a
89
+ charging tariff not as `{operatorId}*T{suffix}`), and `poi-verifier.json`, new here: 106 checks of the verifier
90
+ extensions, meter keys, historical meter evidence, session prices, trust transitions, keys of charging documents,
91
+ trust policy identifications, digests of key statements, offer hashes and publication receipts, against the POI
92
+ fixtures of ChargyWebApp at `fc513cd`, vendored as `tests/vectors/chargy-fc513cd`. Run in `tests/conformance.test.ts`
93
+ as WWCPPOIConformanceTests runs them against this library: a refusal after its control, by its reason; none deviates.
94
+ - `poi-refusals.json` of WWCPPOIConformanceTests `7d43d4b` vendored (`586a339` before a rebase there), of 142 vectors:
95
+ 13 price statements whose price status is none WWCP_POI3 reads (without one; its prices not an array; the prices of a
96
+ tariff not an object; a property or a JSON-LD context besides, of the status or of the prices of a tariff; a tariff
97
+ not named `{operatorId}*T{suffix}` or named twice, also in another spelling; its elements empty, one not an object or
98
+ without price components), refused as both read them, in the words both give. None deviates.
99
+ - `poi-refusals.json` of WWCPPOIConformanceTests `ed91741` vendored, of 273 vectors: 131 versions built from the tests
100
+ of this library and read as WWCP_POI3 reads them, 59 of reading, 18 of references, 33 of written forms, 11 of offers,
101
+ 10 of measurement public keys, refused in the words both give. None deviates. Two of them, offers of `Europe/Berlin`,
102
+ WWCP_POI3 takes where .NET runs without ICU, as it then finds no IANA time zone and compares them in UTC (O5 there).
103
+ - `@vanaheimr/cose` 0.14.0, the codec still `@vanaheimr/metrological-cbor` 0.12: a key of a party of key type RSA (3) is
104
+ read as Styx reads it, identified by its RFC 9679 thumbprint over n and e, and taken as WWCP_POI3 takes it; 0.12.0
105
+ refused it, "Invalid COSE key: The curve of a COSE key must be an integer!". POI names no signature algorithm of RSA
106
+ (SPECIFICATION.md 4), so such a key signs nothing this library verifies, as before.
107
+ - `@vanaheimr/cose` 0.15.0, the codec still `@vanaheimr/metrological-cbor` 0.12. It reads and verifies the
108
+ countersignature of RFC 8152 and holds a key an X.509 certificate writes as `id-RSASSA-PSS` to RSASSA-PSS, as Styx
109
+ `7642de3d` does. This library uses neither, and reads and verifies its keys and signatures as with 0.14.0. For
110
+ development, Playwright 1.65.0 and Vite 8.3.6. TypeScript stays at 6.0: typescript-eslint 8.72.1 requires a version
111
+ below 6.1, and its typed linting needs the compiler API that TypeScript 7 does not ship.
112
+ - `poi-refusals.json` of WWCPPOIConformanceTests `d388929` vendored, of 283 vectors: 10 versions naming a time zone of a
113
+ charging pool or a charging pool template that is none of a region of the IANA time zone database, refused by WWCP_POI3
114
+ since `d1c41ca` and taken by this library, marked as its deviation (D17 there).
115
+ - A change set changes the entities a party embeds, as WWCP_POI3 applies them (`apply.ts`; RoamingNetwork.OfferChanges.cs,
116
+ ProviderChanges.cs, GridChanges.cs and ParkingChanges.cs): the charging tariff offers of charging station operators
117
+ and e-mobility providers, the EVSE, charging station and charging pool groups of e-mobility providers, the grid
118
+ connection points of grid operators, the parking garages, spaces, sensors, space templates, space groups and products
119
+ of parking operators and the parking spaces of charging station operators. Added to the party an `Add` names as its
120
+ parent, found by its identification as its type compares it, e.g. a parking product with case, the properties a change
121
+ set may change, in the words of WWCP_POI3; with their timestamps, but a grid connection point and a parking product,
122
+ which have none. Owned by the party embedding them (4.1), the offers by keys that may sign `tariffs`, the others
123
+ `infrastructure`; a grid connection point by its maintainer, its maintainer changed by it, its grid operator or the
124
+ identity keys of the roaming network operator; also after the earlier changes of the change set, which may add or
125
+ remove them or their party. 0.2.0 refused them as not supported. Of 107 change sets probed against WWCP_POI3 at
126
+ `d1c41ca` (`CreateChangeSet`), the 50 it takes lead to the same content here, and the 57 it refuses are refused here
127
+ too, 34 in the same words; the others in the words of the entity read again without `Change N:`, of the change as
128
+ WWCP_POI3 parses it, or of the written form, where WWCP_POI3 names a property of infrastructure a change set may not
129
+ change.
130
+ - The `effectiveLastChanges` of a snapshot are read as WWCP_POI3 reads them (`TryTakeEffectiveFloors`,
131
+ POIEffectiveLastChange): absent or `null`, or an array of `{entityType, entityId, lastChange}`, a JSON-LD context only
132
+ its own, the timestamp in a form `DateTimeOffset` reads; refused otherwise in its words, "The effective last changes of
133
+ a snapshot must be a JSON array!", "Invalid effective last change '{…}' of a snapshot!". 0.2.0 took any. They are the
134
+ floors of the `lastChange` of effective members POI_API keeps at runtime (SPECIFICATION.md 8.8, point 3), found again
135
+ for what a change set changes; the effective tree takes the `lastChange` of an effective member without them (8.1),
136
+ as WWCP_POI3 does (`EffectiveChargingPoolsOfTheContent`), so this library reads them and keeps none.
137
+ - The preconditions of a change set hold, as WWCP_POI3 checks them (`preconditions.ts`; RoamingNetwork.Preconditions.cs,
138
+ SPECIFICATION.md 4): each names the ETag an entity still has in the version the change set is applied to, after its
139
+ `beforeETags` and before its changes, over the entity as the roaming network embeds it, with everything it embeds, its
140
+ canonical JSON or its deterministic CBOR, in the hash algorithm it names. The entity is found by its type and
141
+ identification as its type compares it, e.g. `DEGEFP1` as `DE*GEF*P1`, among the entities a change set addresses on
142
+ their own (`Flatten`), not a model, which is unique within its manufacturer only, as in WWCP_POI3. Refused otherwise in
143
+ its words, "The change set does not fit this version of the roaming network: Precondition 0: the ChargingPool
144
+ 'DE*GEF*P1' changed, it no longer has the ETag json:sha256:hex:…!", and a precondition not read as it reads one in a
145
+ change set, "Invalid precondition 1!". 0.2.0 refused change sets with preconditions as not supported. Of 79 change sets
146
+ with preconditions probed against WWCP_POI3 at `d1c41ca`, ETags of 40 entities of every kind among them, all are taken
147
+ and refused alike, 70 in the same words, the others refused when read, where the probe reads a precondition on its own.
148
+ - A change set changes elements, as WWCP_POI3 applies them (`elements.ts`, `apply.ts`; POIElements.cs and
149
+ RoamingNetwork.ElementChanges.cs): `AddElement`, `RemoveElement`, `ReplaceElement`, `UpdateElementProperty` and
150
+ `RemoveElementProperty` address an element of a property of an entity by their element path, e.g.
151
+ `chargingConnectors['1'].format`, an element of an array by its identification, as the type of the identifications of
152
+ the property compares them, e.g. `EVSEIds` without case, any other ordinally; an added element where the ordinal order
153
+ puts it, in `templateIds` at the end; an array left without elements removed. Each amounts to the `UpdateProperty` or
154
+ `RemoveProperty` of the property its path starts with, checked and owned as that change (4.1), its old value compared
155
+ with the element, or the property of the element, it addresses; keys and tree hash algorithms are changed as a whole
156
+ only. Element changes WWCP_POI3 does not make are refused when the change set is read: an element change without an
157
+ element path, another change with one, a new value of JSON `null`, of each kind of change what it does not take, e.g.
158
+ an `AddElement` with an old value, a segment of a path without a property name or with an empty identification.
159
+ 0.2.0 refused element changes as not supported. The properties of charging pools, stations, EVSEs, tariffs, groups and
160
+ templates a change set may change are those of WWCP_POI3 (RoamingNetwork.InfrastructureChanges.cs), refused otherwise
161
+ in its words, e.g. "the property 'chargingStations' of a charging pool can not be changed!", and an infrastructure
162
+ entity is named as WWCP_POI3 names it, e.g. "the charging tariff 'DE*GEF*T_AC'". Of 108 element changes probed against
163
+ WWCP_POI3 at `d1c41ca` (`CreateChangeSet`), the 47 it takes lead to the same content here, and the 61 it refuses are
164
+ refused here too, 31 in the same words; the others in the words of the entity read again without `Change N:`, of an
165
+ old value without the value found, or of a change as this library reads it. Of the 107 change sets of embedded
166
+ entities probed before, 93 are now in the same words.
167
+ - The elements of the prices of a charging tariff in a price statement are written as a charging tariff holds them
168
+ (SPECIFICATION.md 12.1, WWCP_POI3 `5a72313`, D18 of the conformance tests), as a version holds the elements of a tariff:
169
+ an element, a price component or restrictions naming a property their type does not define, a number given as a text,
170
+ the days of the week out of their order, the JSON-LD context of an embedded object are refused before the signature,
171
+ "'elements[0].restrictions.maxStateOfCharge' of the prices of the charging tariff 'DE*GEF*T_DC' is not written as a
172
+ charging tariff holds it: the content leaves it out!" under "Invalid price status of the price statement: ". A reader
173
+ not knowing a restriction would else price a session where its signer did not. The written form knows the
174
+ restrictions of an element now (`startTime` to `reservation`, as ChargingTariffRestrictions writes them): a version
175
+ naming another one, e.g. `maxStateOfCharge`, is refused, which 0.2.0 took. The price evidence of a session whose
176
+ statement names a restriction of OCPI, e.g. `max_kwh`, has invalid signatures now (`sessionPrice-conditional-price`).
177
+ `poi-refusals.json` and `poi-verifier.json` of WWCPPOIConformanceTests `c540c7f` vendored, 290 vectors, 7 of them new;
178
+ none deviates.
179
+ - `poi-histories.json` of WWCPPOIConformanceTests `bc4e5a0` vendored: the 13 replays this library left to WWCP_POI3
180
+ (`notApplicable`) hold here as well and are replayed: the references a version holds, e.g. `station-*`, `meter-*`,
181
+ `withdrawn-while-named-*`, checked since `813e1d7`, and the changes of the groups of a provider and of grid connection
182
+ points, applied since `1946013`, each refused in the words of its reason. `tests/conformance.test.ts` 760.
183
+ - `poi-histories.json` of WWCPPOIConformanceTests `70deea0` vendored: 14 replays of the entities a party embeds, as
184
+ `1946013` applies them, in `history-parties`: offers of an operator, signed for `tariffs`, not overlapping; an offer
185
+ and groups of a provider, signed by the provider, not by the operator of the same prefix; a grid connection point
186
+ handed on and named in one change set, by its new maintainer (csharp-review 9); parking data of a parking operator
187
+ and the parking space of a charging station operator, each signed by its own party. `tests/conformance.test.ts` 774.
188
+ - `poi-verifier.json` of WWCPPOIConformanceTests `aef4b38` vendored, with the price evidence of sessions it makes itself
189
+ (`tests/vectors/chargy/POIPrices`): the cases of `POIPrices` of ChargyWebApp `fc513cd`, every signature
190
+ deterministic. 23 `sessionPrice-*` vectors check the same as before on them; `-foreign-tariff` and
191
+ `-conditional-price` stay on the fixtures. Two new ones are taken: `-tariff-of-another-evse`, a genuine price of a
192
+ tariff of the pattern `{operatorId}*T{suffix}` the EVSE does not name, of which none applies, and
193
+ `-conditional-element`, an element restricted by `maxEnergy`, whose price is selected without a rate.
194
+ `tests/conformance.test.ts` 776.
195
+ - Transparency software releases and certificates are identified under their owners, as WWCP_POI3 `045e180` checks it
196
+ (SPECIFICATION.md 4.1, POI3-ISSUES.md S36, `ForeignTransparencySoftware`, `ForeignConformityCertificate`,
197
+ `IsIdentifiedUnder`): the `@id` of a release is the `@id` of its manufacturer, a colon and a name without one
198
+ (`GraphDefined:chargy-1.5.0`), of a certificate the `@id` of the body issuing it alike (`PTB:2026-0042`), the prefix
199
+ compared without case, both trimmed as read. A version holding one identified otherwise is refused before releases or
200
+ certificates given twice, in its words: "The transparency software release 'chargy-1.5.0' of the manufacturer
201
+ 'GraphDefined' is not identified as one of it: by 'GraphDefined:' and a name without a colon!"; so is a change set
202
+ leading to one, after the unknown parking spaces and before the releases given twice. References name them as before.
203
+ Of 38 versions and change sets probed against WWCP_POI3 at `045e180`, all are taken and refused alike, in the same
204
+ words. `tests/releaseIdentifications.test.ts`.
205
+ - The test vectors of a new run of the C# examples, `tests/vectors/csharp-045e180` in place of `csharp-33447ac`: WWCP_POI
206
+ `045e180`, examples A1 to A15, MakeProofs at `2026-11-05T19:46:00.000Z` (`tests/at.ts`). Releases and certificates
207
+ under their owners (`GraphDefined:chargy-1.5.0`, `PTB:2026-0017`, `PTB:2026-0042`); example A15 names the EV Taler
208
+ merchant of DE*GEF, so the head of epoch 2 is revision 11, while `QA.json` stays revision 8, as example A14 left it.
209
+ With them `poi-history.json` (100 vectors), `poi-refusals.json` (296, 6 of them of S36), `poi-histories.json` (75
210
+ replays, 8 of them of S36, the histories naming releases and certificates under their owners) and `poi-qidigital.json`
211
+ of WWCPPOIConformanceTests `2d0780f`. The tests on QA hold the values of the new run; those WWCP_POI3 calculated of
212
+ changed versions (element and embedded changes, preconditions, EV Taler) are calculated again by WWCP_POI3 at
213
+ `045e180`, and this library takes the very same versions. `tests/conformance.test.ts` 794.
214
+ - Required signature roles, as WWCP_POI `12e993a` checks them (POI3-ISSUES.md S24): `requiredSignatureRoles` of a history,
215
+ the roles a commit must be signed in, refused before it is applied where it has no signature in one ("The commit '…'
216
+ is not signed in the role '…'!"), and once its signatures are verified where none of them is by a key the version it
217
+ leads to lets sign in that role ("… by a key that may sign in it!", `keyMaySignIn`): in the role of the roaming
218
+ network operator a signing key certified for it, in the role of a charging station operator a signing key of the
219
+ operator its signer names; leaders and witnesses are the verifier's. So also the commit of a snapshot.
220
+ `requiredCheckpointSignatureRoles`, the roles a checkpoint must be signed in ("The checkpoint '…' is not signed in the
221
+ role '…'!"). A signed commit without a verifier is refused before it is applied, as WWCP_POI does. Signatures of one
222
+ key in one role, e.g. the twin of an ECDSA signature (S11), are kept as given, each verified, and counted once by the
223
+ holder or witness they are of, as WWCP_POI `f7b8643` reads them too (SPECIFICATION.md 5.4): it kept the first alone
224
+ since `12e993a`, so a forged signature behind a genuine one of its key went unchecked. `tests/signatureRoles.test.ts`.
225
+ - A checkpoint is taken with the signatures that verify here, as WWCP_POI `399b7c8` takes it (POI3-ISSUES.md S39,
226
+ SPECIFICATION.md 10.2): `verifyCheckpoint` of a history returns those of its signatures that verify, and the history
227
+ keeps the first of each key and role of them; one that does not verify, invalid or by a key not trusted here, is left
228
+ out, not refused, so that nobody blocks a checkpoint by adding a signature, and a witness trusted elsewhere and not here
229
+ keeps none from it. The roles a checkpoint must be signed in are counted among them: before, a role of a signature
230
+ `verifyCheckpointSignatures` passed over counted ("The checkpoint '…' is not signed in the role '…' by a signature that
231
+ verifies here!", and why the first one was left out). `takeCheckpoint` and a snapshot of a checkpoint hold it with
232
+ those only (`Checkpoint.withSignaturesOnly`). `verifyCheckpointSignatures` returns them as `verified`. The type of
233
+ `verifyCheckpoint` is now `(checkpoint) => readonly RoleSignature[] | undefined`: `undefined`, every signature verifies,
234
+ as before; a callback of a block without `return` is typed `void` and is no longer one.
235
+ - A signature of a commit or checkpoint is read as WWCP_POI3 reads it (`RoamingNetworkCommitSignature.TryParse`): its role,
236
+ time, algorithm, key and value trimmed, its signer as given, and what it signs is what was read; refused when its role,
237
+ signer, algorithm, key or value is empty or whitespace alone (`String.IsNullOrWhiteSpace`), and so is a signature of a
238
+ change set whose algorithm, key or value is ("The … of a signature of … must not be empty!"). Before, this library took
239
+ them, and a role padded with whitespace was not the role.
240
+ - Required signature roles probed against WWCP_POI3 at `12e993a`, `f7b8643` and `399b7c8` (`CheckSignatures` of a
241
+ snapshot, `TryAppend`, `TryAddCheckpoint`), on QA of epoch 2: 1879 cases of roles required of a snapshot, a commit and
242
+ a checkpoint, signed in every role, by keys of the roaming network operator, of DE*GEF and of nobody, by signers named
243
+ in every form, with and without a verifier; a second signature of one key in one role, the same, forged or signed
244
+ later; checkpoints verified by a rule leaving signatures out, forged ones before genuine ones among them; signatures
245
+ read with texts empty, padded and of other types. At `399b7c8` all are taken and refused alike, the checkpoints held with
246
+ the same signatures, the roles in the same words, signatures read refused in the words of this library. Stricter than
247
+ WWCP_POI3 there, which took them: a signer given as a number, an `@context` or another property in a signature of a
248
+ commit or checkpoint, and in the commit of a snapshot an algorithm its epoch does not name. WWCP_POI `b43ff1a` refuses
249
+ them too (POI3-ISSUES.md S40), and `7c6f91c` refuses a signature read in the words of this library, a snapshot naming
250
+ why its commit is refused: probed again at `7c6f91c`, all 1879 alike, word for word.
251
+ - `poi-refusals.json` and `poi-histories.json` of WWCPPOIConformanceTests `215023a` vendored, 806 vectors there, 13 of
252
+ them new: 8 refusals of a signature of the genesis commit or of checkpoint 1 not in its one form (another property,
253
+ `@context`, a signer as a number, a role of whitespace, a signedAt without milliseconds); a replay starting from the
254
+ snapshot of the genesis of epoch 3, its commit signed with Ed448, which the epoch does not name; 4 snapshots of
255
+ checkpoint 0 anchored with a signature that does not verify or a witness the trust anchor does not know (taken, S39), a
256
+ key of one holder signing twice (refused) and with the other holder too (taken). None deviates.
257
+ - What a proof gives of a child array, as WWCP_POI `d35c780` tells it (S29): `givesCompletely`, whether an entity as a proof
258
+ gives it has a child array completely, as an array or none, or pruned or partially; `sizeOf`, how many children it has,
259
+ also where the proof gives only some or none of them. A size or index beyond what this platform holds, and an object as
260
+ the identification of the roaming network, were refused already.
261
+ - No lastChange goes back, as WWCP_POI `12e993a` stamps a change set (SPECIFICATION.md 4, "Timestamps", POI3-ISSUES.md
262
+ S5): with its createdAt, or the lastChange of the roaming network of the version it is applied to, where that is later,
263
+ as the lastChange of the network, of what it changes, adds and embeds, and as the created of what it adds without one.
264
+ Its keys are still checked at its createdAt; nobody is refused for it, only the ETags after it differ (`stampOf`). The
265
+ after ETags of the element and embedded change sets and of the preconditions of the tests, created before QA, are
266
+ those WWCP_POI3 at `12e993a` calculated for the very same changes (67 change sets, all alike). `poi-histories.json` of
267
+ WWCPPOIConformanceTests `249d667` vendored: the three rebased change sets of `history-parties`, created at 08:06:30 on a
268
+ head of 08:07:00, are stamped 08:07:00. `tests/lastChange.test.ts`: every change set of both epochs of QA, created
269
+ before its version, stamped with its lastChange.
270
+ - EV Taler, phase 2, as WWCP_POI `c2d39e5` checks it (concepts/EVTaler.md 5 and 7, `src/evTaler`): the contract terms of
271
+ a step of a session (`EVTalerContractTerms`: version 0, an order, an amount and a maximum fee as GNU Taler writes them,
272
+ the merchant, its exchanges, the times, an auto refund) and their step in `extra.wwcp` (`EVTalerStep`: the roaming
273
+ network, the EVSE, the session, the step after the order before, the EV Taler tariff, the price statement, what it
274
+ covers, from step 2 on the signed meter value at the start, an object as OCPP 2.1 sends it), checked against the proof
275
+ of the station: the operator's merchant and exchanges in the currency of the EV Taler tariff of the EVSE, the price
276
+ statement current when the session began, each step following the one before, the signed start value verified with
277
+ the measurement key of the meter or the station the proof gives, by a transparency software passed in; the amount of a
278
+ step recalculated where the session is priced by one element of the simple profile (`EVTalerRates`), as System.Decimal
279
+ calculates it (`NetDecimal`: 96 bits, 28 places, rounded half to even), rounded up to the minor unit. A `taler://pay`
280
+ URI (`EVTalerPayURI`) names the merchant of the operator. The settlement statement (`EVTalerSettlement`), signed by the
281
+ operator with a key that may sign `payments`, refused without both signed meter values, of the steps of the session,
282
+ its energy and times those of the values, its price recalculated, half away from zero. Read and verified, not signed.
283
+ Of 178 sessions, steps, pay URIs and settlement statements probed against WWCP_POI3 at `c2d39e5`, on station proofs it
284
+ made, all are taken and refused alike, in the same words. `tests/evTalerSessions.test.ts`, on the proof of example A15.
285
+ - EV Taler: a step in minutes costs what it covers, rounded up to the cent, not a cent more, as WWCP_POI `a374855`
286
+ calculates it: the quantity multiplied by the price of an hour before it is divided by 60. A decimal holds no rate of a
287
+ minute such as 0.40 / 60 exactly, and rounding up took its last digit for a cent: 60 minutes at 0.40 EUR an hour were
288
+ 0.41 EUR, 30 minutes 0.21 EUR. Found by the probe of this port. The 178 cases probed again against WWCP_POI3 with
289
+ `a374855`: all alike.
290
+ - `hermodURL` as Hermod reads a URL: no `_` in host names, an empty port, an IPv6 address checked.
291
+ - Reading a version takes about two to three times as long as with 0.2.0, e.g. 1.0 to 1.3 s for 3204 charging pools of
292
+ 12816 EVSEs, each energy meter with a P-256 key of its own, where 0.2.0 took 0.4 s. A check of a version finds the
293
+ members of the operators in their order, their effective charging stations and energy meters and the charging stations
294
+ parking spaces name once (`whileChecking`); the identifications read of texts and the measurement public keys checked,
295
+ the last 65536 of each, are remembered for the next version too, as a history names most of them again. A key of P-256
296
+ takes about 20 µs, a key of RSA about as long as one exponentiation with its modulus, a certificate of ECDSA a few
297
+ milliseconds.
298
+
299
+
300
+ ### Migration
301
+
302
+ - Versions WWCP_POI3 refuses and 0.2.0 took are refused now, in the words of WWCP_POI3; of the probed versions and the
303
+ test vectors, none WWCP_POI3 takes. Messages of refusals checked by their text change where 0.2.0 worded them on its
304
+ own, e.g. a roaming network with keys of its own.
305
+ - A price statement whose price status 0.2.0 took and WWCP_POI3 refuses, e.g. naming the charging tariff
306
+ `DE*POI*FOREIGN`, is refused before its signature is looked at.
307
+ - A charging pool or a charging pool template naming its time zone by a Windows name, an abbreviation or in another case
308
+ than the IANA time zone database, which 0.2.0 took, is refused: it names it as the database writes it, e.g.
309
+ `Europe/Berlin`.
310
+ - `HistoryOptions.verifyCheckpoint` returns the signatures of the checkpoint that verified, `readonly RoleSignature[]`,
311
+ or `undefined` for all of them, e.g. `checkpoint => verifyCheckpointSignatures(checkpoint, trust, options).verified`.
312
+ A callback of a block without `return` no longer compiles; one that throws still refuses the checkpoint. A history,
313
+ `takeCheckpoint` and a snapshot of a checkpoint hold it with those signatures only, its identification the same: what
314
+ an app keeps of a checkpoint it took may hold fewer signatures than it was given (S39).
315
+ - `Change.elementPath` is an array of `ElementPathSegment`, `{propertyName, elementId}`, in place of the JSON objects
316
+ given, and `ChangeSet.preconditions` an array of `Precondition`, `{entityType, entityId, eTag}`, both read as WWCP_POI3
317
+ reads them; the JSON of a change and of a change set stays in its `json`. Both types are exported, and so are
318
+ `MerkleTreeHead`, `PrunedTree` and `TreeNodeKind`, which the API used already.
319
+ - A signature of a commit or checkpoint is read in its one form: its role, signedAt, algorithm, key and value trimmed,
320
+ and refused where one of them or its signer is empty or whitespace alone, where its signer is not a text, or where it
321
+ names an `@context` or another property; so is a signature of a change set whose algorithm, key or value is empty.
322
+ Producers write each signature in this form, as WWCP_POI `7c6f91c` reads it too.
323
+ - A change set created before the `lastChange` of the version it is applied to is stamped with that `lastChange`, not
324
+ with its `createdAt` (S5): the version it leads to, and so its after ETags, differ from those 0.2.0 calculated, and a
325
+ producer calculates them as WWCP_POI `12e993a` does. A change set created after its version, the usual case, is stamped
326
+ with its `createdAt` as before.
327
+ - A transparency software release is identified under its manufacturer, `{manufacturer}:{name}`, and a certificate
328
+ under the body issuing it, `{body}:{name}`, e.g. `GraphDefined:chargy-1.5.0` (S36): a version or change set
329
+ identifying one otherwise, which 0.2.0 took, is refused.
330
+ - The prices of a charging tariff in a price statement are written as a tariff holds them (D18): a statement naming a
331
+ property their type does not define, e.g. the OCPI restriction `max_kwh`, is refused before its signature, and the
332
+ price evidence of a session holding one has invalid signatures. A version naming a restriction outside `startTime` to
333
+ `reservation`, e.g. `maxStateOfCharge`, is refused.
334
+ - A snapshot whose `effectiveLastChanges` WWCP_POI3 does not read, which 0.2.0 took, is refused. Change sets 0.2.0
335
+ refused as not supported, of the entities a party embeds, with element changes or preconditions, are applied now.
336
+ - Reading a version takes two to three times as long as with 0.2.0, about a second for 12816 EVSEs. The package is
337
+ larger, 3.7 MB unpacked where 0.2.0 was 2.2 MB, of it `dist/index.js` 0.9 MB and its source map 2.3 MB.
338
+ - `@vanaheimr/cose` requires ^0.15.0 and `@vanaheimr/metrological-cbor` still ^0.12.0: keep both ranges aligned in
339
+ consumers that use them directly. The minimum runtime remains Node 22.18, and the package remains ESM-only. Without
340
+ Temporal, on Node 22 and 24, a time zone Intl names by another name is taken in any case, e.g. `Asia/KOLKATA`, which
341
+ it names `Asia/Calcutta`; Node 26 takes it only as the database writes it.
342
+
343
+
344
+ ## 0.2.0 (2026-11-02)
345
+
346
+ Shared trust and session verification APIs, previously delivered as the unpublished 0.1.2-dev.0 development candidate.
347
+ The experimental evidence and delegation profiles described below remain experimental in this release.
348
+
349
+ - Shared association of an EVSE, its energy meter and its key, with an explicit normalization of SubjectPublicKeyInfo
350
+ and COSE P-256 keys and a conservative freshness of the observation; no claim of a historical association.
351
+ - Historical meter evidence per reading, and checkpoints verified under the current local authorization.
352
+ - Prices bound to a session, their publication and their rates checked apart.
353
+ - A shared comparison of authenticated versions: rollback and fork constraints the caller keeps durably, historical and
354
+ current versions told apart, gaps filled, a change of the epoch refused unless verified.
355
+ - The charging document keys of a CPO, an authority of their own; experimental delegation of a policy signed by two
356
+ quorums, historical timelines of authorities, and verified epoch continuation and profiles.
357
+ - Experimental receipts of a public retrieval of prices, a policy of witness organizations, networks and clocks of
358
+ its own, restrictions of key usages and a conservative result before the signed start; no witness authorized
359
+ automatically, no claim of the actual start or of the consent of the customer.
360
+ - COSE and Metrological CBOR on ^0.12.0, so that direct and transitive consumers share one codec; existing proof and
361
+ signature fixtures remain valid.
362
+ - `trustPolicyId` is the SHA-256 of the canonical JSON of `{network, holders, minConsensus, urls}`, the URLs as a WHATWG
363
+ URL serializes them without trailing slashes, in their ordinal order, as WWCP_POI3 calculates it
364
+ (`TrustTransition.PolicyIdOf`); in place of their `JSON.stringify`, whose order of properties and escapes are those of
365
+ JavaScript, so that every implementation calculates the same. Every policy identification changes: decisions an app
366
+ keeps under one are made again, and transitions are signed again.
367
+ - A commit is refused without its `json`, `cbor` and `effectiveTree` ETags (SPECIFICATION.md 8.3), as WWCP_POI3 refuses
368
+ it; the epoch change of `tests/vectors/trust-transitions.json` names the ETags of its versions.
369
+ - `trustTransitions.ts` and `documentKeys.ts` with the license header and in the layout of the other sources.
370
+
371
+
372
+ ### Migration
373
+
374
+ - Commits must name all three version ETags: `json`, `cbor` and `effectiveTree`. A commit accepted by 0.1.1 with
375
+ only an effective-tree ETag is now refused. Producers must generate the complete ETags and sign the resulting commits
376
+ and checkpoints again; do not edit previously signed documents or silently repair an archived original.
377
+ - When moving from the unpublished 0.1.2-dev.0 candidate that used `JSON.stringify` for policy identity, recompute
378
+ `trustPolicyId` from canonical JSON. Reconfirm local decisions under the new identity and regenerate and sign affected
379
+ trust transitions. Retain old observations and original evidence; a changed policy identity must not erase known forks
380
+ or rollbacks. Candidates already using canonical JSON keep their policy identities.
381
+ - COSE and Metrological CBOR both require ^0.12.0. Keep both dependency ranges aligned in consumers that use them directly.
382
+ - The minimum runtime remains Node 22.18, and the package remains ESM-only. Local trust decisions, durable observation
383
+ storage and independently authorized witness policies remain the caller's responsibility. No production trust roots
384
+ or witness service are bundled.
385
+
386
+
5
387
  ## 0.1.1 (2026-10-31)
6
388
 
7
389
  `TrustContext`, for apps that import a trust anchor before they trust its keys. `TrustContext.evaluate` checks a key