@orvello/sdk 0.1.0 → 0.2.1

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/dist/index.d.ts CHANGED
@@ -83,6 +83,269 @@ declare function formatAmount(amount: number | string, currency?: string, locale
83
83
  */
84
84
  declare function mapPaymentAccountToBankDetails(account: PaymentAccount): BankAccountDetails;
85
85
 
86
+ type RouteChannelCode = "b" | "k" | "n";
87
+ type RouteIndexEntry = readonly [
88
+ method: string,
89
+ path: string,
90
+ channel: RouteChannelCode,
91
+ authType: string,
92
+ validated: number,
93
+ scopes?: readonly string[]
94
+ ];
95
+ declare const ROUTE_INDEX: Readonly<Record<string, RouteIndexEntry>>;
96
+
97
+ /**
98
+ * Die Route entscheidet, welches Credential mitgeht — nicht der Aufrufer.
99
+ *
100
+ * orvello (node-bill) kennt zwei Bahnen nebeneinander, und sie sind nicht
101
+ * austauschbar:
102
+ *
103
+ * - **bearer** — die Geschaeftsrouten (`unified_bearer`, `frontend_*`). Hier gilt
104
+ * ein OAuth2-Client (client_credentials) oder ein als Bearer gesendeter Token.
105
+ * Das Credential gehoert der *rufenden App*.
106
+ * - **api_key** — die Verwaltungsrouten (`x_api_key_https`), also alles unter
107
+ * `/oauth/clients/external/*`. Hier gilt der Header `x-api-key`. Das Credential
108
+ * gehoert der *Kante* zwischen Verwalter und Dienst.
109
+ *
110
+ * Bis 0.1.0 schickte der Client alles als `Authorization: Bearer`. Die neun
111
+ * Verwaltungsrouten waren damit zwar getippt und aufrufbar, aber grundsaetzlich
112
+ * nicht authentisierbar — ein Loch, das erst beim ersten echten Aufruf sichtbar
113
+ * geworden waere, und dann als `403 Forbidden: Invalid API key` ohne Hinweis auf
114
+ * die Ursache.
115
+ *
116
+ * Der generierte Vertrag traegt `auth.type` an jeder einzelnen Route. Diese Datei
117
+ * liest genau das aus und macht es zur Laufzeitentscheidung. Eine neue Route mit
118
+ * einer neuen Auth-Art faellt damit nicht still in die falsche Bahn, sondern
119
+ * kommt hier an.
120
+ */
121
+
122
+ /** Welche Kopfzeile eine Route verlangt. */
123
+ type OrvelloAuthChannel = "bearer" | "api_key" | "none";
124
+ type OrvelloOperationId = keyof typeof ROUTE_INDEX & string;
125
+ type OrvelloOperation = {
126
+ operationId: string;
127
+ method: string;
128
+ /** Die Vorlage aus dem Vertrag, Platzhalter noch als `:name`. */
129
+ path: string;
130
+ /** Die Auth-Art, wie sie woertlich im Vertrag steht. */
131
+ authType: string;
132
+ /** Was daraus fuer den Aufruf folgt. */
133
+ channel: OrvelloAuthChannel;
134
+ /** Was der Dienst an dieser Route validiert — aus `meta.validated`. */
135
+ validated: {
136
+ params: boolean;
137
+ query: boolean;
138
+ body: boolean;
139
+ };
140
+ /** Die im Vertrag geforderten OAuth2-Scopes, sofern die Auth-Art welche nennt. */
141
+ scopes: readonly string[];
142
+ };
143
+ /**
144
+ * Bildet eine Auth-Art des Vertrags auf die Bahn ab, ueber die sie bedient wird.
145
+ *
146
+ * Unbekannte Arten landen bewusst auf `bearer`: das ist die Bahn aller
147
+ * Geschaeftsrouten und damit die einzige Voreinstellung, die einen neuen,
148
+ * hier noch nicht gesehenen Routentyp nicht sofort unbrauchbar macht.
149
+ */
150
+ declare function authChannelForContractType(authType: string | undefined | null): OrvelloAuthChannel;
151
+ /** Alle Operationen des Vertrags, gegen den dieses SDK gebaut wurde. */
152
+ declare function listOperations(): readonly OrvelloOperation[];
153
+ /** Eine Operation nach ihrer `operationId`, oder `null`, wenn der Vertrag sie nicht kennt. */
154
+ declare function describeOperation(operationId: string): OrvelloOperation | null;
155
+ /**
156
+ * Findet die Route, die ein konkreter Pfad anspricht.
157
+ *
158
+ * ⭐ Woertliche Segmente schlagen Platzhalter. Ohne diese Regel wuerde
159
+ * `GET /oauth/clients/external/list` auf `/oauth/clients/external/:idOrClientId`
160
+ * fallen — beide sind GET mit vier Segmenten — und die Auflistung bekaeme die
161
+ * Auth-Entscheidung einer anderen Route. Dass beide hier dieselbe Bahn
162
+ * verlangen, ist Zufall und kein Verlass.
163
+ */
164
+ declare function resolveOperation(method: string, path: string): OrvelloOperation | null;
165
+ /** Fehlt ein Pfad-Parameter, ist der Aufruf falsch — nicht der Dienst. */
166
+ declare class OrvelloOperationError extends Error {
167
+ readonly operationId: string;
168
+ constructor(message: string, operationId: string);
169
+ }
170
+ /**
171
+ * Setzt die Platzhalter einer Vertrags-Route.
172
+ *
173
+ * Ein fehlender Parameter wirft hier, statt einen Pfad mit `:idOrClientId` darin
174
+ * ans Netz zu geben. Der Dienst antwortete darauf mit 404 oder — schlimmer — mit
175
+ * dem Treffer einer anderen Route.
176
+ */
177
+ declare function buildPath(operationId: string, params?: Record<string, unknown>): string;
178
+
179
+ /**
180
+ * Was dieser Dienst kann — als Daten, ohne Netz und ohne Vermutung.
181
+ *
182
+ * Ein Verbindungs-Verwalter (node-amp) kann Kanten nur dann selbst herstellen,
183
+ * pruefen und reparieren, wenn er weiss, *was die Gegenseite ueberhaupt anbietet*.
184
+ * Bis hierher war das Wissen implizit: irgendwo im Verwalter stand fest
185
+ * einprogrammiert, dass orvello Clients ausstellen kann. Wird eine Faehigkeit dort
186
+ * angenommen und fehlt sie hier, ist das Ergebnis eine Zeile, die gesund aussieht,
187
+ * weil nie jemand gefragt hat.
188
+ *
189
+ * Deshalb leitet sich der Bericht ausschliesslich aus dem mitgelieferten Vertrag
190
+ * ab: eine Faehigkeit gilt genau dann als vorhanden, wenn die zugehoerige
191
+ * Operation im Vertrag steht. Faellt sie in node-bill weg, verschwindet sie beim
192
+ * naechsten `sync:contract` auch hier — niemand muss daran denken.
193
+ *
194
+ * ⚠ Der Bericht sagt, was der Vertrag hergibt, nicht was der Aufrufer darf. Ob ein
195
+ * Credential wirklich traegt, beantwortet allein {@link preflightOrvello}.
196
+ */
197
+
198
+ /**
199
+ * Eine Faehigkeit und die Operationen, an denen sie haengt.
200
+ *
201
+ * `operations` ist der Beleg: wer die Angabe anzweifelt, kann sie gegen den
202
+ * Vertrag nachschlagen, statt dem Wort zu glauben.
203
+ */
204
+ type OrvelloCapability = {
205
+ supported: boolean;
206
+ operations: string[];
207
+ /** Warum nicht — nur gesetzt, wenn `supported` falsch ist. */
208
+ reason?: string;
209
+ };
210
+ type OrvelloCapabilities = {
211
+ service: "orvello";
212
+ sdkVersion: string;
213
+ contractSha256: string;
214
+ /** Wie viele Operationen der Vertrag insgesamt kennt. */
215
+ operationCount: number;
216
+ /** Welche Credential-Bahnen der Vertrag ueberhaupt verlangt. */
217
+ authChannels: Record<OrvelloAuthChannel, number>;
218
+ capabilities: {
219
+ /** Der Dienst nennt seinen eigenen Vertrags-Fingerabdruck (`GET /health/contract`). */
220
+ contractFingerprint: OrvelloCapability;
221
+ /** Ein unauthentisierter Erreichbarkeits-Endpunkt. */
222
+ healthCheck: OrvelloCapability;
223
+ /** OAuth2-Clients fuer andere Apps anlegen, lesen, aendern, loeschen. */
224
+ clientManagement: OrvelloCapability;
225
+ /** Client-Geheimnis erneuern. */
226
+ clientRotation: OrvelloCapability;
227
+ /**
228
+ * Gnadenfrist beim Wechsel: das alte Geheimnis bleibt gueltig, bis es
229
+ * ausdruecklich zurueckgezogen wird — und laesst sich zurueckdrehen.
230
+ */
231
+ rotationGracePeriod: OrvelloCapability;
232
+ /** Zugang sofort entziehen. */
233
+ clientRevocation: OrvelloCapability;
234
+ /** Berechtigungen (entitlements) lesen und setzen. */
235
+ entitlements: OrvelloCapability;
236
+ /** Rechnungen ueber die externe API. */
237
+ invoicing: OrvelloCapability;
238
+ /**
239
+ * Ein serverseitiger Probelauf, der schreibt *als ob*, aber nichts aendert.
240
+ *
241
+ * ⭐ Steht hier bewusst mit dem Grund statt still auf `false`: orvello kennt
242
+ * `dryRun` heute nur in der Buchhaltung, nicht in der Client-Verwaltung. Ein
243
+ * Verwalter, der einen Probelauf braucht, nimmt {@link preflightOrvello} —
244
+ * der ist nebenwirkungsfrei, aber er beweist die Berechtigung, nicht das
245
+ * Ergebnis. Der Unterschied gehoert benannt, nicht verschwiegen.
246
+ */
247
+ serverSideDryRun: OrvelloCapability;
248
+ };
249
+ };
250
+ /**
251
+ * Der Faehigkeitsbericht dieses Dienstes. Rein aus dem Vertrag, kein Netzzugriff,
252
+ * kein Credential noetig — damit ein Verwalter ihn auch dann fuehren kann, wenn
253
+ * die Verbindung gerade nicht steht.
254
+ */
255
+ declare function orvelloCapabilities(): OrvelloCapabilities;
256
+
257
+ /**
258
+ * Der Probelauf: "wuerde dieser Aufruf heute klappen?" — ohne ihn zu tun.
259
+ *
260
+ * Ein Verbindungs-Verwalter muss zwei Dinge auseinanderhalten koennen, die sonst
261
+ * gern zusammenfallen: *darf ich* und *habe ich*. Eine Kante anzulegen erzeugt
262
+ * echte Daten auf beiden Seiten; das ist ein freigegebener Schritt und kein
263
+ * Nebenprodukt einer Pruefung. Trotzdem will man jederzeit — auch turnusmaessig,
264
+ * auch ohne Anlass — wissen, ob der Weg noch traegt.
265
+ *
266
+ * Genau diese Luecke fuellt der Probelauf. Er geht denselben Weg wie der echte
267
+ * Aufruf: dieselbe Basis-URL, dieselbe Credential-Bahn, derselbe Vertrag. Er
268
+ * hoert nur vor dem Schreiben auf. Was er beweist, ist die **Berechtigung**, nicht
269
+ * das **Ergebnis** — und dieser Unterschied steht in jedem Bericht, damit ihn
270
+ * niemand ueberliest.
271
+ *
272
+ * ⭐ Jeder Schritt traegt seinen Grund. Ein `ok: false` ohne Satz ist genau die
273
+ * schweigende Luecke, die aussieht wie Gesundheit.
274
+ */
275
+
276
+ /** Der oeffentliche Erreichbarkeits-Endpunkt, wie ihn der Vertrag fuehrt. */
277
+ declare const HEALTH_PATH: string;
278
+ type PreflightStepName = "operation" | "path-parameters" | "request-shape" | "reachable" | "contract" | "credential-configured" | "credential-accepted";
279
+ type PreflightStep = {
280
+ name: PreflightStepName;
281
+ ok: boolean;
282
+ /** Uebersprungen heisst: nicht gepruefft. Nie "in Ordnung". */
283
+ skipped: boolean;
284
+ /** Was geprueft wurde und was dabei herauskam — in Worten, nicht als Code. */
285
+ detail: string;
286
+ };
287
+ type PreflightReport = {
288
+ ok: boolean;
289
+ operationId: string;
290
+ method: string | null;
291
+ /** Der Pfad, der wirklich gerufen wuerde — Platzhalter bereits gesetzt. */
292
+ path: string | null;
293
+ baseUrl: string | null;
294
+ authChannel: OrvelloAuthChannel | null;
295
+ /**
296
+ * Immer `"none"`. Ein Probelauf schreibt nicht — das ist seine Zusage, nicht
297
+ * eine Eigenschaft des Einzelfalls.
298
+ */
299
+ sideEffects: "none";
300
+ /**
301
+ * Ob der Dienst selbst einen serverseitigen Probelauf dieser Operation kennt.
302
+ * `false` heisst: das hier ist eine Wegpruefung, keine Ergebnisvorschau.
303
+ */
304
+ serverSideDryRun: boolean;
305
+ steps: PreflightStep[];
306
+ problems: string[];
307
+ checkedAt: string;
308
+ };
309
+ /**
310
+ * Was der Probelauf vom Client braucht. Bewusst schmal gehalten, damit die
311
+ * Pruefung nicht am Client haengt und einzeln testbar bleibt.
312
+ */
313
+ type PreflightHost = {
314
+ resolveBaseUrl(): Promise<string>;
315
+ fetchImpl(): typeof globalThis.fetch;
316
+ /** Ist fuer diese Bahn ueberhaupt ein Credential hinterlegt? Ohne Netz. */
317
+ hasCredentialFor(channel: OrvelloAuthChannel): Promise<boolean>;
318
+ /**
319
+ * Ein echter, ausschliesslich lesender Aufruf auf derselben Bahn.
320
+ * Beweist, dass das Credential nicht nur da ist, sondern auch angenommen wird.
321
+ */
322
+ probeCredential(channel: OrvelloAuthChannel, signal?: AbortSignal): Promise<{
323
+ ok: boolean;
324
+ detail: string;
325
+ }>;
326
+ };
327
+ type PreflightOptions = {
328
+ params?: Record<string, unknown>;
329
+ query?: Record<string, unknown>;
330
+ body?: unknown;
331
+ timeoutMs?: number;
332
+ signal?: AbortSignal;
333
+ /**
334
+ * Den teuersten Schritt auslassen: kein echter Aufruf, nur die Frage, ob ein
335
+ * Credential hinterlegt ist. Fuer Massenpruefungen ueber viele Kanten.
336
+ */
337
+ skipCredentialProbe?: boolean;
338
+ };
339
+ /**
340
+ * Prueft einen Aufrufweg, ohne ihn zu gehen.
341
+ *
342
+ * Die Reihenfolge ist Absicht: erst alles, was ohne Netz entschieden werden kann
343
+ * (Vertrag, Parameter, Gestalt), dann die Erreichbarkeit, dann der Vertrag der
344
+ * laufenden Gegenstelle, zuletzt das Credential. So nennt der Bericht bei einem
345
+ * Fehlschlag die *frueheste* Ursache, statt einen Folgefehler zu melden.
346
+ */
347
+ declare function preflightOrvello(host: PreflightHost, operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
348
+
86
349
  type AuthProvider = string | (() => string | Promise<string>) | {
87
350
  apiKey: string;
88
351
  } | {
@@ -91,6 +354,15 @@ type AuthProvider = string | (() => string | Promise<string>) | {
91
354
  scope?: string;
92
355
  tokenUrl?: string;
93
356
  };
357
+ /** Ein Wert, der sich auch erst beim Aufruf ergeben darf. */
358
+ type ValueProvider<T> = T | (() => T | Promise<T>);
359
+ type HeadersProvider = ValueProvider<Record<string, string>>;
360
+ interface CircuitBreakerConfig {
361
+ /** Wie viele Fehlschlaege in Folge den Kreis oeffnen. */
362
+ threshold?: number;
363
+ /** Wie lange danach nicht erneut versucht wird, bevor ein Versuch den Kreis prueft. */
364
+ cooldownMs?: number;
365
+ }
94
366
  interface OrvelloClientConfig {
95
367
  /**
96
368
  * Base URL of the orvello accounting/invoicing service this client talks to.
@@ -101,11 +373,44 @@ interface OrvelloClientConfig {
101
373
  * throws rather than silently aiming at a fixed host.
102
374
  */
103
375
  baseUrl?: BaseUrlProvider;
376
+ /**
377
+ * Das Credential der **Geschaeftsrouten** — ein OAuth2-Client
378
+ * (client_credentials) oder ein fertiger Token. Geht als
379
+ * `Authorization: Bearer` mit. Env: `ORVELLO_OAUTH_CLIENT_ID` /
380
+ * `ORVELLO_OAUTH_CLIENT_SECRET` / `ORVELLO_OAUTH_SCOPE`, ersatzweise
381
+ * `ORVELLO_API_KEY`.
382
+ */
104
383
  auth?: AuthProvider;
384
+ /**
385
+ * Das Credential der **Verwaltungsrouten** (`/oauth/clients/external/*`), also
386
+ * der Header `x-api-key`. Env: `ORVELLO_MANAGEMENT_API_KEY`.
387
+ *
388
+ * ⭐ Das ist bewusst ein zweiter, eigener Wert und keine zweite Schreibweise
389
+ * desselben. Die Geschaeftsrouten gehoeren der rufenden App, die
390
+ * Verwaltungsrouten der Kante zwischen Verwalter und Dienst — wer beides in ein
391
+ * Feld legt, verliert genau die Trennung, die eine Rotation je Kante moeglich
392
+ * macht. Ein Client, der nur Rechnungen schreibt, laesst diesen Wert weg und
393
+ * kann dann auch keine Zugaenge ausstellen. Das ist erwuenscht.
394
+ */
395
+ managementApiKey?: ValueProvider<string>;
396
+ /**
397
+ * Zusaetzliche Kopfzeilen fuer jede Anfrage. Wird vor der Auth-Kopfzeile
398
+ * angewandt, kann sie also nicht versehentlich ueberschreiben.
399
+ */
400
+ headers?: HeadersProvider;
105
401
  fetch?: typeof globalThis.fetch;
106
402
  timeoutMs?: number;
107
403
  maxRetries?: number;
108
404
  retryBaseDelayMs?: number;
405
+ /**
406
+ * Der Sicherungsautomat. `false` schaltet ihn ab.
407
+ *
408
+ * Wiederholungen helfen gegen einen Aussetzer; sie helfen nicht, wenn die
409
+ * Gegenstelle weg ist — dann verlaengern sie nur jede einzelne Anfrage um das
410
+ * volle Zeitlimit mal Versuche. Der Automat beendet diesen Zustand schnell und
411
+ * laut, statt langsam und leise.
412
+ */
413
+ circuitBreaker?: CircuitBreakerConfig | false;
109
414
  }
110
415
  interface RequestOptions {
111
416
  query?: Record<string, unknown>;
@@ -115,7 +420,36 @@ interface RequestOptions {
115
420
  timeoutMs?: number;
116
421
  maxRetries?: number;
117
422
  signal?: AbortSignal;
423
+ /**
424
+ * Die Credential-Bahn ausdruecklich setzen. Normalerweise unnoetig: der Client
425
+ * liest sie aus dem Vertrag der angesprochenen Route. Nur fuer Pfade gedacht,
426
+ * die der mitgelieferte Vertrag (noch) nicht kennt.
427
+ */
428
+ authChannel?: OrvelloAuthChannel;
118
429
  }
430
+ /** Wie {@link RequestOptions}, aber fuer den Aufruf ueber eine `operationId`. */
431
+ interface CallOptions extends RequestOptions {
432
+ params?: Record<string, unknown>;
433
+ body?: unknown;
434
+ }
435
+ type OrvelloHealth = {
436
+ /** Antwortet der Dienst ueberhaupt? */
437
+ available: boolean;
438
+ responseTimeMs: number;
439
+ /**
440
+ * Wurde ein Credential wirklich angenommen? `null` heisst: nicht geprueft,
441
+ * weil keines hinterlegt ist — nie "in Ordnung".
442
+ */
443
+ authenticated: boolean | null;
444
+ error?: string;
445
+ };
446
+ type CircuitBreakerState = {
447
+ open: boolean;
448
+ consecutiveFailures: number;
449
+ lastFailureAt: number | null;
450
+ threshold: number;
451
+ cooldownMs: number;
452
+ };
119
453
  declare class OrvelloApiError extends Error {
120
454
  readonly status: number;
121
455
  readonly statusText: string;
@@ -130,20 +464,103 @@ declare class OrvelloApiError extends Error {
130
464
  declare class OrvelloClient {
131
465
  readonly baseUrl: BaseUrlProvider;
132
466
  private readonly auth?;
467
+ private readonly managementApiKey?;
468
+ private readonly extraHeaders?;
133
469
  private readonly doFetch;
134
470
  private readonly timeoutMs;
135
471
  private readonly maxRetries;
136
472
  private readonly retryBaseDelayMs;
137
473
  private cachedOAuthToken;
474
+ private readonly breakerThreshold;
475
+ private readonly breakerCooldownMs;
476
+ private breakerFailures;
477
+ private breakerLastFailureAt;
138
478
  private _bankAccountCache;
139
479
  private _bankAccountCacheTime;
140
480
  constructor(config?: OrvelloClientConfig);
141
481
  private envBaseUrl;
142
482
  private envAuth;
483
+ private envManagementApiKey;
143
484
  resolveBaseUrl(): Promise<string>;
485
+ private static resolveValue;
486
+ /**
487
+ * Der Verwaltungs-Schluessel, sofern hinterlegt.
488
+ *
489
+ * Ein leerer String zaehlt als "nicht hinterlegt". Sonst waere die haeufigste
490
+ * Fehlkonfiguration — eine gesetzte, aber leere Umgebungsvariable — von einem
491
+ * echten Wert nicht zu unterscheiden, und der Fehler kaeme erst als `403` vom
492
+ * Dienst zurueck.
493
+ */
494
+ private resolveManagementApiKey;
144
495
  private getAuthHeader;
145
496
  private isRetriable;
146
497
  request<T = unknown>(path: string, options?: RequestInit & RequestOptions): Promise<T>;
498
+ private recordSuccess;
499
+ private recordFailure;
500
+ /**
501
+ * Ist der Dienst nach aktuellem Wissen ansprechbar?
502
+ *
503
+ * Antwortet ohne Netzzugriff aus dem Zustand des Automaten. Nach Ablauf der
504
+ * Abkuehlzeit gilt er wieder als ansprechbar — der naechste echte Aufruf
505
+ * entscheidet dann, ob das stimmt.
506
+ */
507
+ isAvailable(): boolean;
508
+ /** Der Zustand des Automaten, unverfaelscht — fuer Diagnose-Oberflaechen. */
509
+ circuitState(): CircuitBreakerState;
510
+ /** Den Automaten von Hand schliessen, etwa nach einer behobenen Stoerung. */
511
+ resetCircuit(): void;
512
+ private assertCircuitClosed;
513
+ /**
514
+ * Eine Operation des Vertrags ueber ihre `operationId` aufrufen.
515
+ *
516
+ * Methode, Pfad und Credential-Bahn kommen aus dem Vertrag; der Aufrufer gibt
517
+ * nur die Werte. Das ist der Weg fuer alles, wofuer es keine getippte Methode
518
+ * gibt — und der Weg, der bei einer neuen Route sofort mitwaechst, statt auf
519
+ * eine Handarbeit in diesem Client zu warten.
520
+ *
521
+ * Der Rueckgabetyp ist bewusst offen: die genauen Typen je Operation stehen im
522
+ * Unterpfad `@orvello/sdk/contract` und werden hier als Typ-Argument gesetzt.
523
+ * Ein `operationId`, den der Vertrag nicht kennt, wirft sofort — nicht erst,
524
+ * wenn der Dienst mit 404 antwortet.
525
+ */
526
+ call<T = unknown>(operationId: string, options?: CallOptions): Promise<T>;
527
+ /**
528
+ * Steht der Dienst, und wird unser Credential angenommen?
529
+ *
530
+ * ⭐ `available` und `authenticated` sind zwei Fragen, und der Bericht haelt sie
531
+ * auseinander. Ein Dienst, der laeuft, aber unser Credential ablehnt, ist nicht
532
+ * "verfuegbar" im Sinne dessen, der ihn benutzen will — und ein `authenticated:
533
+ * null` heisst "nicht gefragt", nie "in Ordnung".
534
+ */
535
+ checkHealth(options?: {
536
+ timeoutMs?: number;
537
+ signal?: AbortSignal;
538
+ }): Promise<OrvelloHealth>;
539
+ /** Was der Vertrag hergibt — ohne Netz, ohne Credential. */
540
+ capabilities(): OrvelloCapabilities;
541
+ /** Spricht die laufende Gegenstelle denselben Vertrag wie dieses SDK? */
542
+ diagnose(options?: {
543
+ timeoutMs?: number;
544
+ signal?: AbortSignal;
545
+ }): Promise<OrvelloDiagnosis>;
546
+ /**
547
+ * Wuerde dieser Aufruf heute klappen? Prueft den ganzen Weg — Erreichbarkeit,
548
+ * Vertrag, Credential — und schreibt dabei nichts.
549
+ *
550
+ * Gedacht fuer Verbindungs-Verwalter: eine Kante laesst sich damit turnusmaessig
551
+ * nachpruefen, ohne sie anzufassen, und vor einem freigegebenen Schreibschritt
552
+ * laesst sich zeigen, was er tun wuerde.
553
+ */
554
+ preflight(operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
555
+ /**
556
+ * Ein ausschliesslich lesender Aufruf auf einer Credential-Bahn.
557
+ *
558
+ * Je Bahn die guenstigste Frage, die ohne Nebenwirkung beantwortet, ob das
559
+ * Credential angenommen wird:
560
+ * - `api_key` → die Auflistung der Zugaenge mit `pageSize=1`
561
+ * - `bearer` → das Holen des Tokens (der Dienst prueft dabei Kennung und Geheimnis)
562
+ */
563
+ private probeCredential;
147
564
  invoices: {
148
565
  search: (query?: InvoicesSearchExternalQuery, options?: RequestOptions) => Promise<InvoicesSearchExternalResponseData>;
149
566
  getById: (id: number, options?: RequestOptions) => Promise<Invoice>;
@@ -219,4 +636,4 @@ declare function createOrvelloClient(config?: OrvelloClientConfig): OrvelloClien
219
636
 
220
637
  declare const CONTRACT_SHA256 = "4efd4e4b669168c9cab5419fa04dd4e26a2029de2d4b10a59918e366189e1072";
221
638
 
222
- export { type AuthProvider, type BankAccountDetails, type BaseUrlProvider, BookkeepingExpensesCreateExternalBody, BookkeepingExpensesCreateExternalResponseData, BookkeepingPaymentsCreateManualExternalBody, BookkeepingPaymentsListAccountsExternalQuery, BookkeepingPaymentsListAccountsExternalResponseData, BookkeepingPaymentsSettleInvoiceExternalBody, BookkeepingPaymentsSettleInvoiceExternalResponseData, BookkeepingRevenue, BookkeepingRevenuesCreateExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalResponseData, CONTRACT_SHA256, CustomerCompaniesCreateExternalBody, CustomerCompaniesSearchExternalQuery, CustomerCompaniesSearchExternalResponseData, CustomerCompaniesUpdateExternalBody, CustomerCompany, DunningGetSettingsExternalResponseData, DunningIssueExternalBody, DunningIssueExternalResponseData, DunningPreviewExternalBody, DunningPreviewExternalResponseData, DunningSuggestionsExternalQuery, DunningSuggestionsExternalResponseData, DunningUpdateSettingsExternalBody, DunningUpdateSettingsExternalResponseData, type ExpenseReceiptUpload, Invoice, InvoicesCreateExternalBody, InvoicesCreateExternalResponseData, InvoicesCreditNoteIssueExternalBody, InvoicesCreditNoteIssueExternalResponseData, InvoicesCreditNotePreviewExternalBody, InvoicesCreditNotePreviewExternalResponseData, InvoicesOverdueExternalResponseData, InvoicesPendingExternalResponseData, InvoicesSearchExternalQuery, InvoicesSearchExternalResponseData, InvoicesSendEmailExternalBody, InvoicesSendEmailExternalResponseData, InvoicesStatusPolicyExternalResponseData, InvoicesUpdateStatusExternalBody, ManagingCompaniesCurrentExternalResponseData, NodeBillUser, Oauth2ExternalClientsCreateBody, Oauth2ExternalClientsCreateResponseData, Oauth2ExternalClientsGetResponseData, Oauth2ExternalClientsListQuery, Oauth2ExternalClientsListResponseData, Oauth2ExternalClientsRetireResponseData, Oauth2ExternalClientsRollbackResponseData, Oauth2ExternalClientsRotateBody, Oauth2ExternalClientsRotateResponseData, Oauth2ExternalClientsUpdateBody, Oauth2ExternalClientsUpdateResponseData, OrvelloApiError, OrvelloClient, type OrvelloClientConfig, type OrvelloContractStatus, type OrvelloDiagnoseOptions, type OrvelloDiagnosis, Payment, PaymentAccount, type RequestOptions, UsersUpdateExternalBody, buildBase64Receipt, calculateVat, createOrvelloClient, diagnoseOrvello, formatAmount, isKleinunternehmer, mapPaymentAccountToBankDetails };
639
+ export { type AuthProvider, type BankAccountDetails, type BaseUrlProvider, BookkeepingExpensesCreateExternalBody, BookkeepingExpensesCreateExternalResponseData, BookkeepingPaymentsCreateManualExternalBody, BookkeepingPaymentsListAccountsExternalQuery, BookkeepingPaymentsListAccountsExternalResponseData, BookkeepingPaymentsSettleInvoiceExternalBody, BookkeepingPaymentsSettleInvoiceExternalResponseData, BookkeepingRevenue, BookkeepingRevenuesCreateExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalBody, BookkeepingRevenuesInvoiceAdjustmentExternalResponseData, CONTRACT_SHA256, type CallOptions, type CircuitBreakerConfig, type CircuitBreakerState, CustomerCompaniesCreateExternalBody, CustomerCompaniesSearchExternalQuery, CustomerCompaniesSearchExternalResponseData, CustomerCompaniesUpdateExternalBody, CustomerCompany, DunningGetSettingsExternalResponseData, DunningIssueExternalBody, DunningIssueExternalResponseData, DunningPreviewExternalBody, DunningPreviewExternalResponseData, DunningSuggestionsExternalQuery, DunningSuggestionsExternalResponseData, DunningUpdateSettingsExternalBody, DunningUpdateSettingsExternalResponseData, type ExpenseReceiptUpload, HEALTH_PATH, type HeadersProvider, Invoice, InvoicesCreateExternalBody, InvoicesCreateExternalResponseData, InvoicesCreditNoteIssueExternalBody, InvoicesCreditNoteIssueExternalResponseData, InvoicesCreditNotePreviewExternalBody, InvoicesCreditNotePreviewExternalResponseData, InvoicesOverdueExternalResponseData, InvoicesPendingExternalResponseData, InvoicesSearchExternalQuery, InvoicesSearchExternalResponseData, InvoicesSendEmailExternalBody, InvoicesSendEmailExternalResponseData, InvoicesStatusPolicyExternalResponseData, InvoicesUpdateStatusExternalBody, ManagingCompaniesCurrentExternalResponseData, NodeBillUser, Oauth2ExternalClientsCreateBody, Oauth2ExternalClientsCreateResponseData, Oauth2ExternalClientsGetResponseData, Oauth2ExternalClientsListQuery, Oauth2ExternalClientsListResponseData, Oauth2ExternalClientsRetireResponseData, Oauth2ExternalClientsRollbackResponseData, Oauth2ExternalClientsRotateBody, Oauth2ExternalClientsRotateResponseData, Oauth2ExternalClientsUpdateBody, Oauth2ExternalClientsUpdateResponseData, OrvelloApiError, type OrvelloAuthChannel, type OrvelloCapabilities, type OrvelloCapability, OrvelloClient, type OrvelloClientConfig, type OrvelloContractStatus, type OrvelloDiagnoseOptions, type OrvelloDiagnosis, type OrvelloHealth, type OrvelloOperation, OrvelloOperationError, type OrvelloOperationId, Payment, PaymentAccount, type PreflightHost, type PreflightOptions, type PreflightReport, type PreflightStep, type PreflightStepName, type RequestOptions, UsersUpdateExternalBody, type ValueProvider, authChannelForContractType, buildBase64Receipt, buildPath, calculateVat, createOrvelloClient, describeOperation, diagnoseOrvello, formatAmount, isKleinunternehmer, listOperations, mapPaymentAccountToBankDetails, orvelloCapabilities, preflightOrvello, resolveOperation };