@mandateops/audit 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,55 @@
1
+ Apache License
2
+
3
+ Version 2.0, January 2004
4
+
5
+ http://www.apache.org/licenses/
6
+
7
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8
+
9
+ 1. Definitions.
10
+
11
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
16
+
17
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
18
+
19
+ "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
20
+
21
+ "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
22
+
23
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
24
+
25
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
26
+
27
+ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
28
+
29
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
30
+
31
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
32
+
33
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
34
+
35
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
36
+
37
+ You must give any other recipients of the Work or Derivative Works a copy of this License; and
38
+
39
+ You must cause any modified files to carry prominent notices stating that You changed the files; and
40
+
41
+ You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
42
+
43
+ If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
44
+
45
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
46
+
47
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
48
+
49
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
50
+
51
+ 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
52
+
53
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
54
+
55
+ END OF TERMS AND CONDITIONS
package/README.md CHANGED
@@ -1,3 +1,34 @@
1
- # Temporary Holding Version
1
+ # @mandateops/audit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The test library for the audit lab. It starts `mandateops`, runs your test body against your
4
+ deployed service, and returns the recorded result. It needs `mandateops` from an `audit-lab` package
5
+ and has no runtime dependencies. `auditRun` runs under Node 22 or later, or Bun, with any test
6
+ runner. Only `@mandateops/audit/bun` needs Bun 1.4.4 or later.
7
+
8
+ Install it from npm, alongside the `mandateops` CLI it drives:
9
+
10
+ ```bash
11
+ bun add --dev @mandateops/audit # or: npm install --save-dev @mandateops/audit
12
+ ```
13
+
14
+ The SDK and the CLI speak a numbered session protocol. A pair from different releases is refused
15
+ before any scenario runs, with the fix named. An `audit-lab` install also carries the SDK of its own
16
+ build at `sdk/mandateops-audit-VERSION.tgz`, for working against a CLI built from source:
17
+ `bun add ./mandateops-audit-VERSION.tgz`.
18
+
19
+ The package ships compiled JavaScript and declarations. TypeScript users of
20
+ `@mandateops/audit/bun`, which wraps `bun:test`, also need `@types/bun`.
21
+
22
+ ```ts
23
+ import { auditRun, defineConfig, runLimit } from "@mandateops/audit";
24
+ import { auditTest } from "@mandateops/audit/bun";
25
+ ```
26
+
27
+ `auditTest` registers one test that fails when the run fails CI. `auditRun` returns the result
28
+ for your own assertions, and `runLimit` gives the matching test timeout.
29
+
30
+ Runs are written to the config's `runsDirectory`, else to `MANDATEOPS_RUNS_DIR` (the GitHub Action
31
+ sets it), else to `runs/` in the working directory.
32
+
33
+ The `audit-lab` README covers the first run, the provider contract, profiles, fault order and
34
+ limits.
package/dist/bun.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /** `auditTest` for Bun's runner; other runners wrap `auditRun` the same way. */
2
+ import { test } from "bun:test";
3
+ import type { AuditConfig, AuditResult, Fixture } from "./index.js";
4
+ export declare function explain(result: AuditResult): string;
5
+ export type AuditTestOptions = Readonly<{
6
+ timeoutMs?: number;
7
+ /** The runner's `test`, or a variant such as `test.failing`. */
8
+ register?: typeof test;
9
+ /** Sees the recorded result, before CI's decision fails the test. */
10
+ onResult?: (result: AuditResult) => void;
11
+ }>;
12
+ /** One test in the customer's suite: a failed body or CI's decision fails it. */
13
+ export declare function auditTest(name: string, config: AuditConfig, body: (fixture: Fixture) => Promise<void>, options?: AuditTestOptions): void;
package/dist/bun.js ADDED
@@ -0,0 +1,28 @@
1
+ /** `auditTest` for Bun's runner; other runners wrap `auditRun` the same way. */
2
+ import { test } from "bun:test";
3
+ import { auditRun, runLimit } from "./index.js";
4
+ export function explain(result) {
5
+ if (result.teardown_failure)
6
+ return `audit failed for ${result.run_id}: its deployment may still be running, so the pass is withdrawn; run \`${result.teardown_failure.recover_command}\``;
7
+ const unresolved = result.properties
8
+ .filter((found) => found.required && found.result !== "satisfied")
9
+ .map((found) => `${found.property}: ${found.result}`);
10
+ const detail = unresolved.length
11
+ ? unresolved.join(", ")
12
+ : `verdict ${result.verdict.verdict}, record published: ${String(result.record_published)}`;
13
+ const refused = result.reading_problems.map((found) => `\n ${found.slot}: ${found.reason}`);
14
+ return `audit failed for ${result.run_id}: ${detail}${refused.join("")}`;
15
+ }
16
+ /** One test in the customer's suite: a failed body or CI's decision fails it. */
17
+ export function auditTest(name, config, body, options = {}) {
18
+ const { timeoutMs = runLimit(config), register = test, onResult } = options;
19
+ register(name, async () => {
20
+ const result = await auditRun(config, body);
21
+ onResult?.(result);
22
+ if (result.assurance !== "backend_and_provider") {
23
+ console.log(`${result.run_id}: ${result.assurance}`);
24
+ }
25
+ if (!result.ci_passed)
26
+ throw new Error(explain(result));
27
+ }, timeoutMs);
28
+ }
@@ -0,0 +1,269 @@
1
+ import type { CapacityReading, HistoryReading, ReadingProfile } from "./reading.js";
2
+ import type { ProviderWire, StagedWire } from "./providers/index.js";
3
+ export { bridge, circleMint, adyen, airwallex, checkout, dwolla, fireblocks, flutterwave, modernTreasury, molliePayouts, paypal, paystack, peach, razorpayx, revolut, stitch, stripePayouts, stripeTransfers, wise, } from "./providers/index.js";
4
+ export type { CheckoutTerms, CurrencyTerms, BridgeTerms, FireblocksTerms, LedgerTerms, MollieTerms, OwnAccountTerms, ProviderWire, SourcedTerms, StagedWire, TermDefaults, WiseRoutes, WiseTerms, } from "./providers/index.js";
5
+ export { parseCapacityReading, parseHistoryReading, ReadingError, requireHistoryFits, } from "./reading.js";
6
+ export type { AttemptEnd, AttemptResult, CapacityReading, Flow, HistoryEvent, HistoryReading, Instruction, MinorUnits, Payout, PayoutState, ReadingProfile, HistoryConsistency, CapacityConsistency, } from "./reading.js";
7
+ /**
8
+ * The largest amount the stand-in holds, the audit core's `u128` maximum.
9
+ * `fixtures/wire/vectors.json` pins it for every reader.
10
+ */
11
+ export declare const SYNTHETIC_MAX_MINOR_UNITS = 340282366920938463463374607431768211455n;
12
+ /** Integer minor units as a decimal string, so no language loses precision. */
13
+ export declare function minorUnits(value: string): string;
14
+ declare const PROPERTIES: readonly ["instruction_binding", "commitment_retention", "retry_identity", "effect_within_authorisation", "reconciliation_consistency", "external_outcome"];
15
+ export type Property = (typeof PROPERTIES)[number];
16
+ declare const PROPERTY_RESULTS: readonly ["satisfied", "violated", "inconclusive", "not_applicable"];
17
+ declare const ASSURANCES: readonly ["backend_and_provider", "backend_and_provider_commitments_not_checked", "money_out_only_commitments_not_checked", "no_assurance"];
18
+ /** What a read-only adapter is given: never an operator or provider credential. */
19
+ export type ReadContext = Readonly<{
20
+ backend: string;
21
+ viewerCredential: string;
22
+ providerPayment: string;
23
+ }>;
24
+ /** Reads the backend, in the shape of `contracts/history-reading.md`. */
25
+ export type Adapter = Readonly<{
26
+ history: (context: ReadContext) => Promise<HistoryReading>;
27
+ capacity: (context: ReadContext) => Promise<CapacityReading>;
28
+ }>;
29
+ export declare const defineAdapter: (adapter: Adapter) => Adapter;
30
+ /** The provider identity every effect must carry. */
31
+ export type ProviderTerms = Readonly<{
32
+ account: string;
33
+ operation: string;
34
+ idempotencyScope: string;
35
+ }>;
36
+ /** The roles the audited service itself holds. */
37
+ export type ServiceRole = "client" | "operator" | "viewer";
38
+ /** Every role a credential variable can serve. */
39
+ export type CredentialRole = ServiceRole | "provider";
40
+ /** The customer's own deployment, as it already is. */
41
+ export type System = Readonly<{
42
+ /** Its Compose file, from the working directory. */
43
+ compose: string;
44
+ /** Where its relative paths resolve from; the Compose file's directory if absent. */
45
+ projectDirectory?: string;
46
+ service: string;
47
+ /** The container port it listens on. */
48
+ port: number;
49
+ /** After a payout settles, how long anything may still act. */
50
+ quiescenceMs: number;
51
+ /** The longest delay between two of its attempts; 0 if it never retries itself. */
52
+ retryDelayMs: number;
53
+ /** Its longest claim on an attempt; 0 if it has none. */
54
+ leaseMs: number;
55
+ workerDeadlineMs?: number;
56
+ providerTerms: ProviderTerms;
57
+ /** The variable it reads its provider's base URL from. */
58
+ providerUrlEnv?: string;
59
+ /**
60
+ * The variables its credentials arrive in. `service` holds client, operator
61
+ * and viewer; the services that call the provider hold provider.
62
+ */
63
+ credentialEnv?: Readonly<Partial<Record<CredentialRole, string>>>;
64
+ /** The services that call the provider; `service` alone if absent. */
65
+ providerClients?: readonly string[];
66
+ /** One of those services, which the host may kill and restart. */
67
+ processService?: string;
68
+ /** How long the deployment may take to become healthy. */
69
+ startupTimeoutS: number;
70
+ /** How long a fault's target may take to commit. */
71
+ faultDeadlineMs: number;
72
+ /** Bound on the host's control and read requests; the host's if absent. */
73
+ controlTimeoutMs?: number;
74
+ /** Bound on one Docker command; the host's if absent. */
75
+ processTimeoutMs?: number;
76
+ /** How long a stopping container may take; the lab's if absent. */
77
+ stopTimeoutS?: number;
78
+ /** How many times a published port is read; the lab's if absent. */
79
+ portReads?: number;
80
+ /** Where each Compose project's `compose.log` is cut; the lab's if absent. */
81
+ logLimitBytes?: number;
82
+ /** Leaves the images built for the run in place at teardown. */
83
+ keepImages?: boolean;
84
+ /**
85
+ * Refuses any service with a `build` key or an image not pinned as
86
+ * `name@sha256:...`, so nothing of the customer's runs during startup.
87
+ */
88
+ requirePrebuiltImages?: boolean;
89
+ /** Values its Compose file interpolates. */
90
+ environment?: Readonly<Record<string, string>>;
91
+ defectStimulus?: string;
92
+ providerMapping?: string;
93
+ /** The provider format the stand-in speaks; the lab's own if absent. */
94
+ providerWire?: ProviderWire | StagedWire;
95
+ }>;
96
+ /** A reviewed financial profile: a reading profile, or effects with no adapter. */
97
+ export type FinancialProfile = ReadingProfile | "payout-effects-only";
98
+ export type AuditConfig = Readonly<{
99
+ /** Explicit until a separately qualified provider emulation exists. */
100
+ provider: "synthetic";
101
+ /** A reviewed financial profile, chosen at setup. */
102
+ financialProfile: FinancialProfile;
103
+ system: System;
104
+ /** Required by every profile but `payout-effects-only`, which refuses one. */
105
+ adapter?: Adapter;
106
+ /**
107
+ * Bounded observation after the test body, while workers may still act.
108
+ * At least the deployment's declared window, or the host refuses to start.
109
+ */
110
+ drainMs: number;
111
+ /**
112
+ * How long a drain goes on when effects keep restarting its window. At
113
+ * least `drainMs`; still changing at this bound leaves the run unresolved.
114
+ */
115
+ drainBoundMs: number;
116
+ capacityLimitMinor: string;
117
+ /** Milliseconds one test body may take. */
118
+ testBudgetMs: number;
119
+ /** How long an aborted body may take to stop before capture starts anyway. */
120
+ abortGraceMs?: number;
121
+ /** Where run directories go, from the working directory; `runs` if absent. */
122
+ runsDirectory?: string;
123
+ /** The host program; `mandateops` on the PATH if absent. */
124
+ hostCommand?: readonly string[];
125
+ }>;
126
+ export declare const defineConfig: (config: AuditConfig) => AuditConfig;
127
+ export type ExpectedPayment = Readonly<{
128
+ reference: string;
129
+ tenant: string;
130
+ agent: string;
131
+ delegation: string;
132
+ account: string;
133
+ destination: string;
134
+ currency: string;
135
+ asset: string;
136
+ network: string;
137
+ amountMinor: string;
138
+ /**
139
+ * What the provider should hold at the end. Required by
140
+ * `payout-effects-only`, and refused by the host under any other profile.
141
+ */
142
+ outcome?: ExpectedOutcome;
143
+ }>;
144
+ export type ExpectedOutcome = "exactly_one_effect" | "no_effect";
145
+ /** A test-declared authorisation: the expectation, not proof of any approval. */
146
+ export type Authorised = Readonly<{
147
+ expected: ExpectedPayment;
148
+ /**
149
+ * Names what the backend sends the provider as `payment`, which is also what
150
+ * adapters read by. Required before `inspect` and before the body ends under
151
+ * any profile with an adapter: an unbound run fails with
152
+ * [`AuditUsageError`]. Optional under `payout-effects-only`, where no
153
+ * reading depends on it.
154
+ */
155
+ bindProviderPayment: (payment: string) => Promise<void>;
156
+ }>;
157
+ export type PropertyDecision = Readonly<{
158
+ property: Property;
159
+ result: (typeof PROPERTY_RESULTS)[number];
160
+ required: boolean;
161
+ }>;
162
+ /** A reading that could not be used, and why, naming the field. */
163
+ export type ReadingProblem = Readonly<{
164
+ slot: string;
165
+ reason: string;
166
+ }>;
167
+ /** What the host sealed. */
168
+ export type SealedResult = Readonly<{
169
+ run_id: string;
170
+ ci_passed: boolean;
171
+ /** What a pass covers: read it before calling a run audited. */
172
+ assurance: (typeof ASSURANCES)[number];
173
+ /** What the result assumes about effects after observation stopped. */
174
+ assumption?: string;
175
+ properties: readonly PropertyDecision[];
176
+ verdict: Readonly<{
177
+ verdict: string;
178
+ findings?: readonly Readonly<{
179
+ rule: string;
180
+ }>[];
181
+ reasons?: readonly unknown[];
182
+ }>;
183
+ record_published: boolean;
184
+ }>;
185
+ /** A deployment that may have outlived its run, and what removes it. */
186
+ export type TeardownFailure = Readonly<{
187
+ recover_command: string;
188
+ }>;
189
+ export type AuditResult = SealedResult & Readonly<{
190
+ /** Why an adapter reading is missing from the record, if one is. */
191
+ reading_problems: readonly ReadingProblem[];
192
+ /** Set when the sealed pass was withdrawn: the deployment outlived the run. */
193
+ teardown_failure?: TeardownFailure;
194
+ }>;
195
+ /** The test body failed. The run is sealed and `result` records it. */
196
+ export declare class AuditTestFailure extends Error {
197
+ readonly result: AuditResult;
198
+ readonly cause: unknown;
199
+ constructor(result: AuditResult, cause: unknown);
200
+ }
201
+ /** The SDK was used against its contract; the message says how to correct it. */
202
+ export declare class AuditUsageError extends Error {
203
+ readonly name = "AuditUsageError";
204
+ }
205
+ type Credentials = Readonly<Record<ServiceRole, string>>;
206
+ /**
207
+ * The session protocol this SDK speaks. The host announces its own when
208
+ * ready; the two must match, as they do for an SDK shipped with its CLI.
209
+ */
210
+ export declare const SESSION_PROTOCOL = 2;
211
+ /** Why a host of another protocol is refused, and how to fix it. */
212
+ export declare function protocolMismatch(announced: number | undefined): string;
213
+ /** A sealed result, checked before anything reads it. */
214
+ export declare function parseResult(value: unknown): SealedResult;
215
+ export type LossMode = "cut_connection" | "hold_response" | "crash_process";
216
+ export type Fixture = Readonly<{
217
+ /** The deployed service's base URL. Optional convenience for `fetch`. */
218
+ app: string;
219
+ /** Generated for this session; a test never holds a provider credential. */
220
+ credentials: Credentials;
221
+ provider: Readonly<{
222
+ expectPayment: (expected: ExpectedPayment) => Promise<Authorised>;
223
+ }>;
224
+ faults: Readonly<{
225
+ /**
226
+ * Gates the authorised payment's committed response, synchronously. One
227
+ * fault at a time: arm, optionally `established`, then `release`.
228
+ */
229
+ loseResponseAfterCommit: (target: Readonly<{
230
+ payment: Authorised;
231
+ mode: LossMode;
232
+ }>) => Promise<void>;
233
+ /**
234
+ * Resolves once the fault took effect; a hold stays held until `release`.
235
+ * Needs an armed fault that is not yet released.
236
+ */
237
+ established: () => Promise<void>;
238
+ /**
239
+ * Ends the armed fault. Released before it took effect, it leaves the run
240
+ * unable to show the stimulus, so the run does not pass.
241
+ */
242
+ release: () => Promise<void>;
243
+ /** Has the stand-in decline the authorised payment's next request. */
244
+ refuseNext: () => Promise<void>;
245
+ }>;
246
+ /** Takes adapter readings while an attempt is unresolved; needs a binding. */
247
+ inspect: () => Promise<void>;
248
+ /** Aborted when the test budget runs out: pass it to the customer's calls. */
249
+ signal: AbortSignal;
250
+ }>;
251
+ /**
252
+ * The whole run, for a test runner's own timeout: startup, the body, closing
253
+ * work on either side of the longest wait, and teardown, which may take as
254
+ * long as startup. The host enforces each bound; this only stays above them.
255
+ */
256
+ export declare const runLimit: (config: AuditConfig) => number;
257
+ /**
258
+ * Refuses, before anything starts, a run that could only end inconclusive.
259
+ *
260
+ * @throws {AuditUsageError} when the profile and adapter do not go together.
261
+ */
262
+ export declare function requireRunnable(config: AuditConfig): void;
263
+ export declare function wireInstruction(expected: ExpectedPayment): Record<string, string>;
264
+ type Body = (fixture: Fixture) => Promise<void>;
265
+ /**
266
+ * Run one audited test and return the recorded result without judging it. A
267
+ * body that fails still seals the run, then rejects with [`AuditTestFailure`].
268
+ */
269
+ export declare function auditRun(config: AuditConfig, body: Body, runId?: string): Promise<AuditResult>;