@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.
- package/CHANGELOG.md +46 -2
- package/LICENSE.md +356 -0
- package/NOTICE.md +8 -0
- package/README.md +29 -140
- package/conformance/cases.json +50 -764
- package/conformance/subject-adapter.ts +31 -0
- package/dist/boundary-fixture.d.ts +24 -0
- package/dist/boundary-fixture.d.ts.map +1 -0
- package/dist/boundary-fixture.js +34 -0
- package/dist/boundary-fixture.js.map +1 -0
- package/dist/index.d.ts +68 -156
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -77
- package/dist/index.js.map +1 -1
- package/dist/vocabulary.d.ts +3 -57
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +12 -84
- package/dist/vocabulary.js.map +1 -1
- package/docs/assets/adl.svg +11 -0
- package/docs/assets/brand/adl-horizontal-white.svg +1 -0
- package/docs/assets/brand/adl-horizontal.svg +1 -0
- package/docs/assets/brand/adl-stacked-white.svg +1 -0
- package/docs/assets/brand/adl-stacked.svg +1 -0
- package/docs/assets/brand/manifest.json +30 -0
- package/docs/authoring-guide.md +37 -416
- package/package.json +17 -12
- package/spec/manifest.schema.json +646 -439
- package/LICENSE +0 -661
- package/LICENSING.md +0 -51
- package/TRADEMARKS.md +0 -30
- package/dist/conformance.d.ts +0 -41
- package/dist/conformance.d.ts.map +0 -1
- package/dist/conformance.js +0 -486
- package/dist/conformance.js.map +0 -1
- package/examples/meridian-bank/README.md +0 -65
- package/examples/meridian-bank/example.spec.ts +0 -162
- package/examples/meridian-bank/fixtures/payout-status-replay.json +0 -19
- package/examples/meridian-bank/fixtures/payout-status-settled.json +0 -19
- package/examples/meridian-bank/fixtures/payout-submit-accepted.json +0 -26
- package/examples/meridian-bank/fixtures/payout-submit-declined.json +0 -25
- package/examples/meridian-bank/fixtures/statement-camt053.json +0 -45
- package/examples/meridian-bank/fixtures/webhook-payout-settled.json +0 -11
- 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.
|
package/dist/conformance.d.ts
DELETED
|
@@ -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"}
|
package/dist/conformance.js
DELETED
|
@@ -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
|
package/dist/conformance.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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"}
|