@hyperscale0/adl 1.0.0-alpha.2 → 1.0.0-beta.10

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 (43) hide show
  1. package/CHANGELOG.md +46 -2
  2. package/LICENSE.md +356 -0
  3. package/NOTICE.md +8 -0
  4. package/README.md +29 -140
  5. package/conformance/cases.json +50 -764
  6. package/conformance/subject-adapter.ts +31 -0
  7. package/dist/boundary-fixture.d.ts +24 -0
  8. package/dist/boundary-fixture.d.ts.map +1 -0
  9. package/dist/boundary-fixture.js +34 -0
  10. package/dist/boundary-fixture.js.map +1 -0
  11. package/dist/index.d.ts +68 -156
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +100 -77
  14. package/dist/index.js.map +1 -1
  15. package/dist/vocabulary.d.ts +3 -57
  16. package/dist/vocabulary.d.ts.map +1 -1
  17. package/dist/vocabulary.js +12 -84
  18. package/dist/vocabulary.js.map +1 -1
  19. package/docs/assets/adl.svg +11 -0
  20. package/docs/assets/brand/adl-horizontal-white.svg +1 -0
  21. package/docs/assets/brand/adl-horizontal.svg +1 -0
  22. package/docs/assets/brand/adl-stacked-white.svg +1 -0
  23. package/docs/assets/brand/adl-stacked.svg +1 -0
  24. package/docs/assets/brand/manifest.json +30 -0
  25. package/docs/authoring-guide.md +37 -416
  26. package/package.json +17 -12
  27. package/spec/manifest.schema.json +646 -439
  28. package/LICENSE +0 -661
  29. package/LICENSING.md +0 -51
  30. package/TRADEMARKS.md +0 -30
  31. package/dist/conformance.d.ts +0 -41
  32. package/dist/conformance.d.ts.map +0 -1
  33. package/dist/conformance.js +0 -486
  34. package/dist/conformance.js.map +0 -1
  35. package/examples/meridian-bank/README.md +0 -65
  36. package/examples/meridian-bank/example.spec.ts +0 -162
  37. package/examples/meridian-bank/fixtures/payout-status-replay.json +0 -19
  38. package/examples/meridian-bank/fixtures/payout-status-settled.json +0 -19
  39. package/examples/meridian-bank/fixtures/payout-submit-accepted.json +0 -26
  40. package/examples/meridian-bank/fixtures/payout-submit-declined.json +0 -25
  41. package/examples/meridian-bank/fixtures/statement-camt053.json +0 -45
  42. package/examples/meridian-bank/fixtures/webhook-payout-settled.json +0 -11
  43. package/examples/meridian-bank/index.ts +0 -262
package/LICENSING.md DELETED
@@ -1,51 +0,0 @@
1
- # Licensing
2
-
3
- The code in this repository is Copyright 2026 Hyperscale LLC and is licensed
4
- under the GNU Affero General Public License version 3 only
5
- (`AGPL-3.0-only`). The full text is in [`LICENSE`](./LICENSE).
6
-
7
- ## What the AGPL asks of you
8
-
9
- Two obligations matter in practice.
10
-
11
- **If you distribute a copy in object form**, modified or not, you make its
12
- Corresponding Source available under the same license.
13
-
14
- **If you run a modified copy as a network service**, section 13 applies: the
15
- users interacting with it over the network get an offer of the source of the
16
- version you are running. Validating adapters with an unmodified copy behind
17
- your own service does not trigger this. Changing the vocabulary, the registry
18
- loader, or the conformance runner and then serving that change does.
19
-
20
- Using `@hyperscale0/adl` as a library inside your own program is a
21
- combined work under the AGPL. If that does not fit how you ship, take the
22
- commercial license instead.
23
-
24
- ## Commercial license
25
-
26
- Hyperscale LLC sells a commercial license to organisations that cannot accept
27
- the AGPL, for the usual reasons: a proprietary adapter that links ADL, a
28
- hosted service you will not open, a procurement policy that refuses copyleft.
29
- It grants the same code under ordinary commercial terms with no source
30
- obligation.
31
-
32
- Ask through <https://hyperscale0.ai>.
33
-
34
- ## The license covers code, not marks
35
-
36
- "Hyperscale" is a trademark of Hyperscale LLC. A copyright license says nothing
37
- about trademarks in either direction, so [TRADEMARKS.md](TRADEMARKS.md) draws
38
- that boundary.
39
-
40
- ## The format is not this implementation of it
41
-
42
- ADL the format is separate from this package, which implements it. The
43
- JSON Schema in [`spec/`](spec) and the conformance cases in
44
- [`conformance/`](conformance) are data describing a format, and anyone may
45
- write their own validator or registry loader against them, in any language,
46
- under any license, without touching this code.
47
-
48
- What you may then say about it is a trademark question, not a copyright one.
49
- [TRADEMARKS.md](TRADEMARKS.md) has the rule: claim that you pass a version of
50
- the conformance suite only when you pass that version's published cases
51
- unmodified.
package/TRADEMARKS.md DELETED
@@ -1,30 +0,0 @@
1
- # Trademarks
2
-
3
- "Hyperscale" and "ADL" are trademarks of Hyperscale LLC.
4
-
5
- The AGPL covers the code in this repository and nothing else. It grants no
6
- right to use the Hyperscale name, the Hyperscale logo, or any other Hyperscale
7
- mark, and it never mentions them: a copyright license says nothing about
8
- trademarks either way.
9
-
10
- What that means in practice:
11
-
12
- - **Yes**, you may say your adapter is written in ADL, or that it passes
13
- Hyperscale conformance. Accurate, factual references to the project are fine.
14
- - **No**, you may not name your package, product, service, or organization in a
15
- way that suggests Hyperscale LLC published it or endorses it, and you may not
16
- use the marks in a logo, domain, or app icon of your own.
17
-
18
- ## Claiming compatibility
19
-
20
- An independent implementation of ADL or of its conformance
21
- runner may say it "passes the Hyperscale ADL conformance suite version X"
22
- only while it passes the published cases for that version, unmodified.
23
- [`conformance/cases.json`](conformance/cases.json) is the whole test: no
24
- skipped case, no edited expectation, no local fork of the fixtures.
25
-
26
- That claim is a statement about your implementation, so keep the marks out of
27
- its name and off its logo, and do not present it as endorsement or
28
- certification by Hyperscale LLC. We certify nothing; the suite does.
29
-
30
- Forks stay welcome. Rename the package and drop the marks.
@@ -1,41 +0,0 @@
1
- /**
2
- * Partner-bank conformance: the certification gate an adapter passes before it
3
- * may serve the family live. Registry load validation
4
- * (`createProviderAdapterRegistry`) proves a declaration is well-formed; this
5
- * module proves it is OPERABLE against the Bank Reference Model -- the
6
- * bank-agnostic contract distilled from observed bank behavior. Every rule
7
- * names the operational failure it prevents, and every rule fails closed: a
8
- * fact the adapter leaves unestablished is a finding, never a default.
9
- *
10
- * The checks are declaration-level on purpose. A partner-bank adapter is a
11
- * declaration (bindings, operation map, webhook plans, profile facts); the
12
- * runtime that executes it is generic. What certification must prove is that
13
- * the declared facts are complete enough for that runtime to poll, classify,
14
- * reconcile, and dedupe without guessing.
15
- */
16
- import type { ProviderAdapter, ProviderAdapterVocabulary } from "./index.js";
17
- /**
18
- * Every rule this suite can report. Grows append-only: a released code is
19
- * never renamed or removed, so consumers may switch on codes without a
20
- * fallback arm going stale. `conformance/cases.json` must exercise all of
21
- * them, and `test/conformance-cases.spec.ts` fails when one is unexercised.
22
- */
23
- export declare const partnerBankConformanceCodes: readonly ["partner_bank_profile_missing", "operation_map_empty", "required_operation_missing", "response_envelope_unclassified", "response_envelope_unconfirmed", "status_enquiry_missing", "status_enquiry_without_rest_egress", "egress_direction_incoherent", "lifecycle_terminals_incomplete", "lifecycle_intake_missing", "lifecycle_spelling_blank", "lifecycle_spelling_conflict", "duplicate_verdicts_unmapped", "statement_debit_reference_unestablished", "statement_formats_empty", "statement_window_missing", "statement_window_incomplete", "charges_unestablished", "charge_narrative_unestablished", "vat_narrative_unestablished", "value_date_offset_invalid", "cutoff_window_regression", "cutoff_clock_invalid", "resource_binding_missing"];
24
- export type PartnerBankConformanceCode = (typeof partnerBankConformanceCodes)[number];
25
- export interface PartnerBankConformanceFinding {
26
- readonly code: PartnerBankConformanceCode;
27
- readonly message: string;
28
- /** Dotted location inside the adapter declaration, for the fix. */
29
- readonly path: string;
30
- }
31
- /**
32
- * Every conformance finding for one adapter. The profile-independent checks
33
- * (operations, egress coherence, bindings) run even when the profile is
34
- * missing, so one run reports everything it can see; a missing profile leads
35
- * the list. An empty result is the certification. Callers wanting a hard
36
- * stop use `certifyPartnerBankAdapter`.
37
- */
38
- export declare function partnerBankConformanceFindings<Vocabulary extends ProviderAdapterVocabulary>(adapter: ProviderAdapter<Vocabulary>): readonly PartnerBankConformanceFinding[];
39
- /** Throw with every finding listed; return silently on a certified adapter. */
40
- export declare function certifyPartnerBankAdapter<Vocabulary extends ProviderAdapterVocabulary>(adapter: ProviderAdapter<Vocabulary>): void;
41
- //# sourceMappingURL=conformance.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAEV,eAAe,EACf,yBAAyB,EAG1B,MAAM,YAAY,CAAC;AAGpB;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,kuBAyB9B,CAAC;AAEX,MAAM,MAAM,0BAA0B,GACpC,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAeD;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,SAAS,yBAAyB,EAE5C,OAAO,EAAE,eAAe,CAAC,UAAU,CAAC,GACnC,SAAS,6BAA6B,EAAE,CA2B1C;AAED,+EAA+E;AAC/E,wBAAgB,yBAAyB,CACvC,UAAU,SAAS,yBAAyB,EAC5C,OAAO,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,IAAI,CAW5C"}
@@ -1,486 +0,0 @@
1
- /**
2
- * Partner-bank conformance: the certification gate an adapter passes before it
3
- * may serve the family live. Registry load validation
4
- * (`createProviderAdapterRegistry`) proves a declaration is well-formed; this
5
- * module proves it is OPERABLE against the Bank Reference Model -- the
6
- * bank-agnostic contract distilled from observed bank behavior. Every rule
7
- * names the operational failure it prevents, and every rule fails closed: a
8
- * fact the adapter leaves unestablished is a finding, never a default.
9
- *
10
- * The checks are declaration-level on purpose. A partner-bank adapter is a
11
- * declaration (bindings, operation map, webhook plans, profile facts); the
12
- * runtime that executes it is generic. What certification must prove is that
13
- * the declared facts are complete enough for that runtime to poll, classify,
14
- * reconcile, and dedupe without guessing.
15
- */
16
- import { statementAvailabilities } from "./vocabulary.js";
17
- /**
18
- * Every rule this suite can report. Grows append-only: a released code is
19
- * never renamed or removed, so consumers may switch on codes without a
20
- * fallback arm going stale. `conformance/cases.json` must exercise all of
21
- * them, and `test/conformance-cases.spec.ts` fails when one is unexercised.
22
- */
23
- export const partnerBankConformanceCodes = [
24
- "partner_bank_profile_missing",
25
- "operation_map_empty",
26
- "required_operation_missing",
27
- "response_envelope_unclassified",
28
- "response_envelope_unconfirmed",
29
- "status_enquiry_missing",
30
- "status_enquiry_without_rest_egress",
31
- "egress_direction_incoherent",
32
- "lifecycle_terminals_incomplete",
33
- "lifecycle_intake_missing",
34
- "lifecycle_spelling_blank",
35
- "lifecycle_spelling_conflict",
36
- "duplicate_verdicts_unmapped",
37
- "statement_debit_reference_unestablished",
38
- "statement_formats_empty",
39
- "statement_window_missing",
40
- "statement_window_incomplete",
41
- "charges_unestablished",
42
- "charge_narrative_unestablished",
43
- "vat_narrative_unestablished",
44
- "value_date_offset_invalid",
45
- "cutoff_window_regression",
46
- "cutoff_clock_invalid",
47
- "resource_binding_missing",
48
- ];
49
- /**
50
- * The Bank Reference Model's operation floor per bank capability: the
51
- * commands an adapter must bind before the capability is served at all. An
52
- * adapter cannot dodge a command-level rule by not declaring the command.
53
- * Capabilities outside this table carry no floor beyond a non-empty map.
54
- */
55
- const brmRequiredOperations = {
56
- bank_credit: ["deposit.record"],
57
- beneficiary_verification: ["beneficiary.verify"],
58
- financial_address_provisioning: ["financial_address.activate"],
59
- payout_execution: ["payout.submit"],
60
- };
61
- /**
62
- * Every conformance finding for one adapter. The profile-independent checks
63
- * (operations, egress coherence, bindings) run even when the profile is
64
- * missing, so one run reports everything it can see; a missing profile leads
65
- * the list. An empty result is the certification. Callers wanting a hard
66
- * stop use `certifyPartnerBankAdapter`.
67
- */
68
- export function partnerBankConformanceFindings(adapter) {
69
- const declarationFindings = [
70
- ...operationFindings(adapter),
71
- ...bindingFindings(adapter),
72
- ];
73
- const profile = adapter.profile;
74
- if (!profile) {
75
- return [
76
- {
77
- code: "partner_bank_profile_missing",
78
- message: "no partner-bank profile is declared, so none of the bank facts " +
79
- "(lifecycle vocabulary, statement identity, windows, charges) " +
80
- "exist for the runtime to operate from",
81
- path: "profile",
82
- },
83
- ...declarationFindings,
84
- ];
85
- }
86
- return [
87
- ...declarationFindings,
88
- ...lifecycleFindings(profile),
89
- ...statementFindings(profile),
90
- ...chargeFindings(profile),
91
- ...windowFindings(profile),
92
- ];
93
- }
94
- /** Throw with every finding listed; return silently on a certified adapter. */
95
- export function certifyPartnerBankAdapter(adapter) {
96
- const findings = partnerBankConformanceFindings(adapter);
97
- if (findings.length === 0)
98
- return;
99
- const lines = findings.map((finding) => ` - [${finding.code}] ${finding.path}: ${finding.message}`);
100
- throw new Error(`${adapter.provider}:${adapter.capability} failed partner-bank ` +
101
- `conformance (${findings.length} finding${findings.length === 1 ? "" : "s"}):\n` +
102
- lines.join("\n"));
103
- }
104
- function operationFindings(adapter) {
105
- const findings = [];
106
- const bindings = Object.entries(adapter.operationMap).filter((entry) => entry[1] !== undefined);
107
- // An adapter with no operations serves nothing, and a rule scoped to a
108
- // command must not be dodgeable by deleting the command.
109
- if (bindings.length === 0) {
110
- findings.push({
111
- code: "operation_map_empty",
112
- message: "no operations are bound, so the capability cannot be served and " +
113
- "every command-level rule is vacuously green",
114
- path: "operationMap",
115
- });
116
- }
117
- for (const required of brmRequiredOperations[adapter.capability] ?? []) {
118
- if (bindings.some(([operation]) => operation === required))
119
- continue;
120
- findings.push({
121
- code: "required_operation_missing",
122
- message: `capability ${adapter.capability} must bind ${required}; without ` +
123
- "it the capability's command surface does not exist",
124
- path: `operationMap.${required}`,
125
- });
126
- }
127
- // A provider response exists to classify only where the runtime sends the
128
- // provider a command and reads an answer: tenant-initiated bindings on an
129
- // outbound egress mode. Observation-recorded settlements carry no response
130
- // of their own, and an envelope declared there would be a borrowed fact.
131
- const outboundEgress = adapter.egress === "rest" || adapter.egress === "sync_clearance";
132
- for (const [operation, binding] of bindings) {
133
- const path = `operationMap.${operation}`;
134
- const commandCarriesResponse = outboundEgress && binding.direction === "tenant_initiated";
135
- // An absent class on a real command means the runtime cannot tell
136
- // acceptance from rejection, and `unconfirmed_until_live` is the honest
137
- // authoring state for exactly that gap -- neither may serve live,
138
- // because a rejection read as silence strands money in flight.
139
- if (commandCarriesResponse && !binding.envelope) {
140
- findings.push({
141
- code: "response_envelope_unclassified",
142
- message: "no response envelope class is declared, so the runtime cannot " +
143
- "classify this command's outcome",
144
- path: `${path}.envelope`,
145
- });
146
- }
147
- if (binding.envelope === "unconfirmed_until_live") {
148
- findings.push({
149
- code: "response_envelope_unconfirmed",
150
- message: "the envelope class is declared unconfirmed; certification is the " +
151
- "licence to serve live, so the class must be established first",
152
- path: `${path}.envelope`,
153
- });
154
- }
155
- // Poll-first read-after-write: a REST command's response can be lost
156
- // after the bank acted on it. Without an authoritative status enquiry
157
- // the adapter's only options are guessing or double-submitting.
158
- if (adapter.egress === "rest" &&
159
- binding.direction === "tenant_initiated" &&
160
- !binding.statusEnquiry) {
161
- findings.push({
162
- code: "status_enquiry_missing",
163
- message: "a tenant-initiated REST command declares no status enquiry, so a " +
164
- "lost response can only be resolved by guessing or resubmitting",
165
- path: `${path}.statusEnquiry`,
166
- });
167
- }
168
- // The exemption is earned by the egress mode, never by authoring
169
- // silence: an enquiry path on an adapter that performs no REST egress
170
- // is a plan the runtime can never execute.
171
- if (adapter.egress !== "rest" && binding.statusEnquiry) {
172
- findings.push({
173
- code: "status_enquiry_without_rest_egress",
174
- message: `a status enquiry is declared but egress is ${adapter.egress}, ` +
175
- "so the runtime has no transport to execute it",
176
- path: `${path}.statusEnquiry`,
177
- });
178
- }
179
- // Sending nothing (`none`) or reconciling from files (`batch_reconcile`)
180
- // cannot carry a tenant-initiated command; declaring one there promises
181
- // an outbound call the egress mode cannot make.
182
- if ((adapter.egress === "none" || adapter.egress === "batch_reconcile") &&
183
- binding.direction === "tenant_initiated") {
184
- findings.push({
185
- code: "egress_direction_incoherent",
186
- message: `a tenant-initiated command is bound but egress is ` +
187
- `${adapter.egress}, which performs no per-command outbound call`,
188
- path: `${path}.direction`,
189
- });
190
- }
191
- }
192
- return findings;
193
- }
194
- function lifecycleFindings(profile) {
195
- const findings = [];
196
- const path = "profile.lifecycleVocabulary";
197
- const canonicalStates = new Set(Object.values(profile.lifecycleVocabulary));
198
- // Tri-state settlement is the model's spine: a submitted payment ends
199
- // processed, failed, or returned, and the poll lane owns the terminals. A
200
- // vocabulary that cannot spell one of them leaves that ending unclassifiable
201
- // and the payout polling forever.
202
- const missingTerminals = ["processed", "failed", "returned"].filter((state) => !canonicalStates.has(state));
203
- if (missingTerminals.length > 0) {
204
- findings.push({
205
- code: "lifecycle_terminals_incomplete",
206
- message: `no bank spelling maps to ${missingTerminals.join(", ")}; a payment ` +
207
- "ending there would be unclassifiable and poll forever",
208
- path,
209
- });
210
- }
211
- // An ack proves the bank took the instruction, never that money moved.
212
- // Without an intake state every ack would have to be graded terminal or
213
- // dropped.
214
- if (!canonicalStates.has("received") && !canonicalStates.has("accepted")) {
215
- findings.push({
216
- code: "lifecycle_intake_missing",
217
- message: "no bank spelling maps to received or accepted, so an " +
218
- "acknowledgement has no non-terminal state to land on",
219
- path,
220
- });
221
- }
222
- // Banks spell one verdict several ways (case drift, trailing spaces), so
223
- // runtimes match spellings after trimming and upper-casing. A spelling that
224
- // is empty after that normalization matches nothing; two spellings that
225
- // collide under it while naming different canonical states make the
226
- // classification order-dependent.
227
- const normalized = new Map();
228
- for (const [spelling, state] of Object.entries(profile.lifecycleVocabulary)) {
229
- const token = spelling.trim().toUpperCase();
230
- if (token.length === 0) {
231
- findings.push({
232
- code: "lifecycle_spelling_blank",
233
- message: "a lifecycle spelling is empty after trimming, so it can never " +
234
- "match a bank status token",
235
- path,
236
- });
237
- continue;
238
- }
239
- const existing = normalized.get(token);
240
- if (existing && existing.state !== state) {
241
- findings.push({
242
- code: "lifecycle_spelling_conflict",
243
- message: `"${spelling}" and "${existing.spelling}" normalize to the same ` +
244
- `token but map to ${state} and ${existing.state}`,
245
- path: `${path}.${spelling}`,
246
- });
247
- continue;
248
- }
249
- normalized.set(token, { spelling, state });
250
- }
251
- // The dedupe spine is reference-based by load law (a non-empty dedupeKeys
252
- // list), so the bank answers a crash-recovery resubmission with a duplicate
253
- // verdict graded against the original's outcome. An adapter that cannot
254
- // classify those verdicts reads its own recovery as a fresh failure.
255
- if (!canonicalStates.has("duplicate_original_succeeded") ||
256
- !canonicalStates.has("duplicate_original_rejected")) {
257
- findings.push({
258
- code: "duplicate_verdicts_unmapped",
259
- message: "the vocabulary cannot classify duplicate verdicts, so a recovery " +
260
- "resubmission over the dedupe spine reads as a fresh failure",
261
- path,
262
- });
263
- }
264
- return findings;
265
- }
266
- function statementFindings(profile) {
267
- const findings = [];
268
- // Statements are bank truth; reconciliation has nothing to prove the ledger
269
- // against without at least one fetchable format.
270
- if (profile.statementFormats.length === 0) {
271
- findings.push({
272
- code: "statement_formats_empty",
273
- message: "no statement format is declared, so reconciliation has no bank " +
274
- "truth to prove the ledger against",
275
- path: "profile.statementFormats",
276
- });
277
- }
278
- // A statement debit line carries two references -- the bank's own entry
279
- // reference and the client reference the instruction was sent with -- and
280
- // banks disagree about which comes back. Left unestablished, every payout
281
- // the platform instructed looks like an unexplained debit.
282
- if (!profile.statementDebitReference) {
283
- findings.push({
284
- code: "statement_debit_reference_unestablished",
285
- message: "which reference ties a statement debit to its instruction is not " +
286
- "established, so every instructed payout reads as an unexplained " +
287
- "debit",
288
- path: "profile.statementDebitReference",
289
- });
290
- }
291
- return findings;
292
- }
293
- function chargeFindings(profile) {
294
- const findings = [];
295
- const charges = profile.charges;
296
- // The profile allows an absent charge model as honest authoring; a
297
- // certified adapter cannot leave it open, because the bank's own charge
298
- // debits would land as unexplained statement lines.
299
- if (!charges) {
300
- return [
301
- {
302
- code: "charges_unestablished",
303
- message: "the bank's charge billing is unmodeled, so its own charge debits " +
304
- "would land as unexplained statement lines",
305
- path: "profile.charges",
306
- },
307
- ];
308
- }
309
- // Post-hoc charges arrive as bank-initiated debits recognized only by their
310
- // narrative wording; a separate VAT line is its own debit with its own
311
- // wording. Each mode in play needs at least one declared prefix.
312
- const chargeNarratives = charges.narratives?.charge ?? [];
313
- if (charges.posting === "post_hoc" && chargeNarratives.length === 0) {
314
- findings.push({
315
- code: "charge_narrative_unestablished",
316
- message: "charges post after the payment but no charge narrative prefix is " +
317
- "declared, so the bank's charge debits are unrecognizable",
318
- path: "profile.charges.narratives.charge",
319
- });
320
- }
321
- const vatNarratives = charges.narratives?.vat ?? [];
322
- if (charges.vat === "separate_line" && vatNarratives.length === 0) {
323
- findings.push({
324
- code: "vat_narrative_unestablished",
325
- message: "VAT arrives as its own ledger line but no VAT narrative prefix is " +
326
- "declared, so the tax debits are unrecognizable",
327
- path: "profile.charges.narratives.vat",
328
- });
329
- }
330
- return findings;
331
- }
332
- function windowFindings(profile) {
333
- const findings = [];
334
- const cutoff = profile.windows.paymentCutoff;
335
- const beforeDays = valueDateOffsetDays(cutoff.beforeCutoffValueDate);
336
- const afterDays = valueDateOffsetDays(cutoff.afterCutoffValueDate);
337
- // The type says `D+<number>`, but a plain-JS consumer can send anything
338
- // ("T+1", "D+1.5"), and a malformed offset must be a finding rather than a
339
- // NaN that slides through every comparison below.
340
- if (beforeDays === null) {
341
- findings.push({
342
- code: "value_date_offset_invalid",
343
- message: `"${cutoff.beforeCutoffValueDate}" is not a D+<days> offset with a ` +
344
- "non-negative whole number of days",
345
- path: "profile.windows.paymentCutoff.beforeCutoffValueDate",
346
- });
347
- }
348
- if (afterDays === null) {
349
- findings.push({
350
- code: "value_date_offset_invalid",
351
- message: `"${cutoff.afterCutoffValueDate}" is not a D+<days> offset with a ` +
352
- "non-negative whole number of days",
353
- path: "profile.windows.paymentCutoff.afterCutoffValueDate",
354
- });
355
- }
356
- // Registry load validates the cutoff clock too, but certification is the
357
- // public gate a third-party adapter author runs, so it must not stay green
358
- // on a clock the runtime would misread. Intl.DateTimeFormat reads an
359
- // undefined timeZone as the runtime default, so presence comes before
360
- // validity.
361
- if (typeof cutoff.time !== "string" || !/^\d{2}:\d{2}$/.test(cutoff.time)) {
362
- findings.push({
363
- code: "cutoff_clock_invalid",
364
- message: `paymentCutoff.time "${String(cutoff.time)}" is not an HH:MM ` +
365
- "wall-clock time",
366
- path: "profile.windows.paymentCutoff.time",
367
- });
368
- }
369
- if (!isValidTimeZone(cutoff.timeZone)) {
370
- findings.push({
371
- code: "cutoff_clock_invalid",
372
- message: `paymentCutoff.timeZone "${String(cutoff.timeZone)}" is not a valid ` +
373
- "IANA time zone, so the cutoff cannot be read on the bank's clock",
374
- path: "profile.windows.paymentCutoff.timeZone",
375
- });
376
- }
377
- // Missing the cutoff can only push value later, and the bank must be able
378
- // to honor its own after-cutoff value date within its forward window. Two
379
- // independent facts, reported independently.
380
- if (beforeDays !== null && afterDays !== null && afterDays < beforeDays) {
381
- findings.push({
382
- code: "cutoff_window_regression",
383
- message: `after-cutoff value date D+${afterDays} is earlier than ` +
384
- `before-cutoff D+${beforeDays}; missing a cutoff cannot move value ` +
385
- "earlier",
386
- path: "profile.windows.paymentCutoff",
387
- });
388
- }
389
- if (afterDays !== null && profile.windows.valueDateMaxDaysAhead < afterDays) {
390
- findings.push({
391
- code: "cutoff_window_regression",
392
- message: `the forward window ends ${profile.windows.valueDateMaxDaysAhead} ` +
393
- `days out but the after-cutoff value date needs D+${afterDays}`,
394
- path: "profile.windows.valueDateMaxDaysAhead",
395
- });
396
- }
397
- // Every declared statement format needs its fetch window, and an
398
- // end-of-day format pages over history, so its window needs the paging
399
- // facts (how far back, how many days per request).
400
- for (const format of profile.statementFormats) {
401
- const window = profile.windows.statements[format];
402
- if (!window) {
403
- findings.push({
404
- code: "statement_window_missing",
405
- message: `statement format ${format} is declared but has no fetch window, ` +
406
- "so the runtime cannot schedule its retrieval",
407
- path: `profile.windows.statements.${format}`,
408
- });
409
- continue;
410
- }
411
- // TS requires availability, but a plain-JS consumer can send a window
412
- // without one or with a spelling outside the enum, and every rule below
413
- // branches on it -- an unrecognized value must not slide through green.
414
- if (!statementAvailabilities.includes(window.availability)) {
415
- findings.push({
416
- code: "statement_window_incomplete",
417
- message: `statement format ${format} declares availability ` +
418
- `"${String(window.availability)}", which is not one of ` +
419
- `${statementAvailabilities.join(", ")}, so the runtime cannot ` +
420
- "schedule its retrieval",
421
- path: `profile.windows.statements.${format}.availability`,
422
- });
423
- continue;
424
- }
425
- if (window.availability === "T-1" &&
426
- (!isPositiveInteger(window.lookbackDays) ||
427
- !isPositiveInteger(window.statementDaysPerRequest))) {
428
- findings.push({
429
- code: "statement_window_incomplete",
430
- message: `end-of-day format ${format} pages over history but declares no ` +
431
- "positive lookbackDays and statementDaysPerRequest",
432
- path: `profile.windows.statements.${format}`,
433
- });
434
- }
435
- }
436
- return findings;
437
- }
438
- function bindingFindings(adapter) {
439
- const findings = [];
440
- const bindings = adapter.bindings;
441
- const claimed = new Set();
442
- const require = (kind, path) => {
443
- if (bindings[kind] !== undefined || claimed.has(kind))
444
- return;
445
- claimed.add(kind);
446
- // Provider facts commit onto platform resources through a declared match
447
- // mode; a resource the adapter settles without one has no lawful way to
448
- // bind the bank's answer.
449
- findings.push({
450
- code: "resource_binding_missing",
451
- message: `resource kind ${kind} is settled by this adapter but declares no ` +
452
- "binding mode, so provider facts have no lawful way to commit",
453
- path,
454
- });
455
- };
456
- for (const binding of Object.values(adapter.operationMap)) {
457
- if (!binding)
458
- continue;
459
- require(binding.resourceKind, `bindings.${binding.resourceKind}`);
460
- }
461
- for (const plan of Object.values(adapter.webhookMap)) {
462
- require(plan.resourceKind, `bindings.${plan.resourceKind}`);
463
- }
464
- return findings;
465
- }
466
- /** Parse `D+<days>`; null for anything that is not a whole-day offset. */
467
- function valueDateOffsetDays(offset) {
468
- const match = /^D\+(0|[1-9]\d*)$/.exec(offset);
469
- return match ? Number(match[1]) : null;
470
- }
471
- function isPositiveInteger(value) {
472
- return value !== undefined && Number.isInteger(value) && value > 0;
473
- }
474
- /** The type says string, but a plain-JS consumer can send anything. */
475
- function isValidTimeZone(timeZone) {
476
- if (typeof timeZone !== "string")
477
- return false;
478
- try {
479
- new Intl.DateTimeFormat("en", { timeZone });
480
- return true;
481
- }
482
- catch {
483
- return false;
484
- }
485
- }
486
- //# sourceMappingURL=conformance.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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"}