@orvello/sdk 0.1.0 → 0.2.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/dist/index.d.cts CHANGED
@@ -83,6 +83,267 @@ 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
+ type PreflightStepName = "operation" | "path-parameters" | "request-shape" | "reachable" | "contract" | "credential-configured" | "credential-accepted";
277
+ type PreflightStep = {
278
+ name: PreflightStepName;
279
+ ok: boolean;
280
+ /** Uebersprungen heisst: nicht gepruefft. Nie "in Ordnung". */
281
+ skipped: boolean;
282
+ /** Was geprueft wurde und was dabei herauskam — in Worten, nicht als Code. */
283
+ detail: string;
284
+ };
285
+ type PreflightReport = {
286
+ ok: boolean;
287
+ operationId: string;
288
+ method: string | null;
289
+ /** Der Pfad, der wirklich gerufen wuerde — Platzhalter bereits gesetzt. */
290
+ path: string | null;
291
+ baseUrl: string | null;
292
+ authChannel: OrvelloAuthChannel | null;
293
+ /**
294
+ * Immer `"none"`. Ein Probelauf schreibt nicht — das ist seine Zusage, nicht
295
+ * eine Eigenschaft des Einzelfalls.
296
+ */
297
+ sideEffects: "none";
298
+ /**
299
+ * Ob der Dienst selbst einen serverseitigen Probelauf dieser Operation kennt.
300
+ * `false` heisst: das hier ist eine Wegpruefung, keine Ergebnisvorschau.
301
+ */
302
+ serverSideDryRun: boolean;
303
+ steps: PreflightStep[];
304
+ problems: string[];
305
+ checkedAt: string;
306
+ };
307
+ /**
308
+ * Was der Probelauf vom Client braucht. Bewusst schmal gehalten, damit die
309
+ * Pruefung nicht am Client haengt und einzeln testbar bleibt.
310
+ */
311
+ type PreflightHost = {
312
+ resolveBaseUrl(): Promise<string>;
313
+ fetchImpl(): typeof globalThis.fetch;
314
+ /** Ist fuer diese Bahn ueberhaupt ein Credential hinterlegt? Ohne Netz. */
315
+ hasCredentialFor(channel: OrvelloAuthChannel): Promise<boolean>;
316
+ /**
317
+ * Ein echter, ausschliesslich lesender Aufruf auf derselben Bahn.
318
+ * Beweist, dass das Credential nicht nur da ist, sondern auch angenommen wird.
319
+ */
320
+ probeCredential(channel: OrvelloAuthChannel, signal?: AbortSignal): Promise<{
321
+ ok: boolean;
322
+ detail: string;
323
+ }>;
324
+ };
325
+ type PreflightOptions = {
326
+ params?: Record<string, unknown>;
327
+ query?: Record<string, unknown>;
328
+ body?: unknown;
329
+ timeoutMs?: number;
330
+ signal?: AbortSignal;
331
+ /**
332
+ * Den teuersten Schritt auslassen: kein echter Aufruf, nur die Frage, ob ein
333
+ * Credential hinterlegt ist. Fuer Massenpruefungen ueber viele Kanten.
334
+ */
335
+ skipCredentialProbe?: boolean;
336
+ };
337
+ /**
338
+ * Prueft einen Aufrufweg, ohne ihn zu gehen.
339
+ *
340
+ * Die Reihenfolge ist Absicht: erst alles, was ohne Netz entschieden werden kann
341
+ * (Vertrag, Parameter, Gestalt), dann die Erreichbarkeit, dann der Vertrag der
342
+ * laufenden Gegenstelle, zuletzt das Credential. So nennt der Bericht bei einem
343
+ * Fehlschlag die *frueheste* Ursache, statt einen Folgefehler zu melden.
344
+ */
345
+ declare function preflightOrvello(host: PreflightHost, operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
346
+
86
347
  type AuthProvider = string | (() => string | Promise<string>) | {
87
348
  apiKey: string;
88
349
  } | {
@@ -91,6 +352,15 @@ type AuthProvider = string | (() => string | Promise<string>) | {
91
352
  scope?: string;
92
353
  tokenUrl?: string;
93
354
  };
355
+ /** Ein Wert, der sich auch erst beim Aufruf ergeben darf. */
356
+ type ValueProvider<T> = T | (() => T | Promise<T>);
357
+ type HeadersProvider = ValueProvider<Record<string, string>>;
358
+ interface CircuitBreakerConfig {
359
+ /** Wie viele Fehlschlaege in Folge den Kreis oeffnen. */
360
+ threshold?: number;
361
+ /** Wie lange danach nicht erneut versucht wird, bevor ein Versuch den Kreis prueft. */
362
+ cooldownMs?: number;
363
+ }
94
364
  interface OrvelloClientConfig {
95
365
  /**
96
366
  * Base URL of the orvello accounting/invoicing service this client talks to.
@@ -101,11 +371,44 @@ interface OrvelloClientConfig {
101
371
  * throws rather than silently aiming at a fixed host.
102
372
  */
103
373
  baseUrl?: BaseUrlProvider;
374
+ /**
375
+ * Das Credential der **Geschaeftsrouten** — ein OAuth2-Client
376
+ * (client_credentials) oder ein fertiger Token. Geht als
377
+ * `Authorization: Bearer` mit. Env: `ORVELLO_OAUTH_CLIENT_ID` /
378
+ * `ORVELLO_OAUTH_CLIENT_SECRET` / `ORVELLO_OAUTH_SCOPE`, ersatzweise
379
+ * `ORVELLO_API_KEY`.
380
+ */
104
381
  auth?: AuthProvider;
382
+ /**
383
+ * Das Credential der **Verwaltungsrouten** (`/oauth/clients/external/*`), also
384
+ * der Header `x-api-key`. Env: `ORVELLO_MANAGEMENT_API_KEY`.
385
+ *
386
+ * ⭐ Das ist bewusst ein zweiter, eigener Wert und keine zweite Schreibweise
387
+ * desselben. Die Geschaeftsrouten gehoeren der rufenden App, die
388
+ * Verwaltungsrouten der Kante zwischen Verwalter und Dienst — wer beides in ein
389
+ * Feld legt, verliert genau die Trennung, die eine Rotation je Kante moeglich
390
+ * macht. Ein Client, der nur Rechnungen schreibt, laesst diesen Wert weg und
391
+ * kann dann auch keine Zugaenge ausstellen. Das ist erwuenscht.
392
+ */
393
+ managementApiKey?: ValueProvider<string>;
394
+ /**
395
+ * Zusaetzliche Kopfzeilen fuer jede Anfrage. Wird vor der Auth-Kopfzeile
396
+ * angewandt, kann sie also nicht versehentlich ueberschreiben.
397
+ */
398
+ headers?: HeadersProvider;
105
399
  fetch?: typeof globalThis.fetch;
106
400
  timeoutMs?: number;
107
401
  maxRetries?: number;
108
402
  retryBaseDelayMs?: number;
403
+ /**
404
+ * Der Sicherungsautomat. `false` schaltet ihn ab.
405
+ *
406
+ * Wiederholungen helfen gegen einen Aussetzer; sie helfen nicht, wenn die
407
+ * Gegenstelle weg ist — dann verlaengern sie nur jede einzelne Anfrage um das
408
+ * volle Zeitlimit mal Versuche. Der Automat beendet diesen Zustand schnell und
409
+ * laut, statt langsam und leise.
410
+ */
411
+ circuitBreaker?: CircuitBreakerConfig | false;
109
412
  }
110
413
  interface RequestOptions {
111
414
  query?: Record<string, unknown>;
@@ -115,7 +418,36 @@ interface RequestOptions {
115
418
  timeoutMs?: number;
116
419
  maxRetries?: number;
117
420
  signal?: AbortSignal;
421
+ /**
422
+ * Die Credential-Bahn ausdruecklich setzen. Normalerweise unnoetig: der Client
423
+ * liest sie aus dem Vertrag der angesprochenen Route. Nur fuer Pfade gedacht,
424
+ * die der mitgelieferte Vertrag (noch) nicht kennt.
425
+ */
426
+ authChannel?: OrvelloAuthChannel;
118
427
  }
428
+ /** Wie {@link RequestOptions}, aber fuer den Aufruf ueber eine `operationId`. */
429
+ interface CallOptions extends RequestOptions {
430
+ params?: Record<string, unknown>;
431
+ body?: unknown;
432
+ }
433
+ type OrvelloHealth = {
434
+ /** Antwortet der Dienst ueberhaupt? */
435
+ available: boolean;
436
+ responseTimeMs: number;
437
+ /**
438
+ * Wurde ein Credential wirklich angenommen? `null` heisst: nicht geprueft,
439
+ * weil keines hinterlegt ist — nie "in Ordnung".
440
+ */
441
+ authenticated: boolean | null;
442
+ error?: string;
443
+ };
444
+ type CircuitBreakerState = {
445
+ open: boolean;
446
+ consecutiveFailures: number;
447
+ lastFailureAt: number | null;
448
+ threshold: number;
449
+ cooldownMs: number;
450
+ };
119
451
  declare class OrvelloApiError extends Error {
120
452
  readonly status: number;
121
453
  readonly statusText: string;
@@ -130,20 +462,103 @@ declare class OrvelloApiError extends Error {
130
462
  declare class OrvelloClient {
131
463
  readonly baseUrl: BaseUrlProvider;
132
464
  private readonly auth?;
465
+ private readonly managementApiKey?;
466
+ private readonly extraHeaders?;
133
467
  private readonly doFetch;
134
468
  private readonly timeoutMs;
135
469
  private readonly maxRetries;
136
470
  private readonly retryBaseDelayMs;
137
471
  private cachedOAuthToken;
472
+ private readonly breakerThreshold;
473
+ private readonly breakerCooldownMs;
474
+ private breakerFailures;
475
+ private breakerLastFailureAt;
138
476
  private _bankAccountCache;
139
477
  private _bankAccountCacheTime;
140
478
  constructor(config?: OrvelloClientConfig);
141
479
  private envBaseUrl;
142
480
  private envAuth;
481
+ private envManagementApiKey;
143
482
  resolveBaseUrl(): Promise<string>;
483
+ private static resolveValue;
484
+ /**
485
+ * Der Verwaltungs-Schluessel, sofern hinterlegt.
486
+ *
487
+ * Ein leerer String zaehlt als "nicht hinterlegt". Sonst waere die haeufigste
488
+ * Fehlkonfiguration — eine gesetzte, aber leere Umgebungsvariable — von einem
489
+ * echten Wert nicht zu unterscheiden, und der Fehler kaeme erst als `403` vom
490
+ * Dienst zurueck.
491
+ */
492
+ private resolveManagementApiKey;
144
493
  private getAuthHeader;
145
494
  private isRetriable;
146
495
  request<T = unknown>(path: string, options?: RequestInit & RequestOptions): Promise<T>;
496
+ private recordSuccess;
497
+ private recordFailure;
498
+ /**
499
+ * Ist der Dienst nach aktuellem Wissen ansprechbar?
500
+ *
501
+ * Antwortet ohne Netzzugriff aus dem Zustand des Automaten. Nach Ablauf der
502
+ * Abkuehlzeit gilt er wieder als ansprechbar — der naechste echte Aufruf
503
+ * entscheidet dann, ob das stimmt.
504
+ */
505
+ isAvailable(): boolean;
506
+ /** Der Zustand des Automaten, unverfaelscht — fuer Diagnose-Oberflaechen. */
507
+ circuitState(): CircuitBreakerState;
508
+ /** Den Automaten von Hand schliessen, etwa nach einer behobenen Stoerung. */
509
+ resetCircuit(): void;
510
+ private assertCircuitClosed;
511
+ /**
512
+ * Eine Operation des Vertrags ueber ihre `operationId` aufrufen.
513
+ *
514
+ * Methode, Pfad und Credential-Bahn kommen aus dem Vertrag; der Aufrufer gibt
515
+ * nur die Werte. Das ist der Weg fuer alles, wofuer es keine getippte Methode
516
+ * gibt — und der Weg, der bei einer neuen Route sofort mitwaechst, statt auf
517
+ * eine Handarbeit in diesem Client zu warten.
518
+ *
519
+ * Der Rueckgabetyp ist bewusst offen: die genauen Typen je Operation stehen im
520
+ * Unterpfad `@orvello/sdk/contract` und werden hier als Typ-Argument gesetzt.
521
+ * Ein `operationId`, den der Vertrag nicht kennt, wirft sofort — nicht erst,
522
+ * wenn der Dienst mit 404 antwortet.
523
+ */
524
+ call<T = unknown>(operationId: string, options?: CallOptions): Promise<T>;
525
+ /**
526
+ * Steht der Dienst, und wird unser Credential angenommen?
527
+ *
528
+ * ⭐ `available` und `authenticated` sind zwei Fragen, und der Bericht haelt sie
529
+ * auseinander. Ein Dienst, der laeuft, aber unser Credential ablehnt, ist nicht
530
+ * "verfuegbar" im Sinne dessen, der ihn benutzen will — und ein `authenticated:
531
+ * null` heisst "nicht gefragt", nie "in Ordnung".
532
+ */
533
+ checkHealth(options?: {
534
+ timeoutMs?: number;
535
+ signal?: AbortSignal;
536
+ }): Promise<OrvelloHealth>;
537
+ /** Was der Vertrag hergibt — ohne Netz, ohne Credential. */
538
+ capabilities(): OrvelloCapabilities;
539
+ /** Spricht die laufende Gegenstelle denselben Vertrag wie dieses SDK? */
540
+ diagnose(options?: {
541
+ timeoutMs?: number;
542
+ signal?: AbortSignal;
543
+ }): Promise<OrvelloDiagnosis>;
544
+ /**
545
+ * Wuerde dieser Aufruf heute klappen? Prueft den ganzen Weg — Erreichbarkeit,
546
+ * Vertrag, Credential — und schreibt dabei nichts.
547
+ *
548
+ * Gedacht fuer Verbindungs-Verwalter: eine Kante laesst sich damit turnusmaessig
549
+ * nachpruefen, ohne sie anzufassen, und vor einem freigegebenen Schreibschritt
550
+ * laesst sich zeigen, was er tun wuerde.
551
+ */
552
+ preflight(operationId: string, options?: PreflightOptions): Promise<PreflightReport>;
553
+ /**
554
+ * Ein ausschliesslich lesender Aufruf auf einer Credential-Bahn.
555
+ *
556
+ * Je Bahn die guenstigste Frage, die ohne Nebenwirkung beantwortet, ob das
557
+ * Credential angenommen wird:
558
+ * - `api_key` → die Auflistung der Zugaenge mit `pageSize=1`
559
+ * - `bearer` → das Holen des Tokens (der Dienst prueft dabei Kennung und Geheimnis)
560
+ */
561
+ private probeCredential;
147
562
  invoices: {
148
563
  search: (query?: InvoicesSearchExternalQuery, options?: RequestOptions) => Promise<InvoicesSearchExternalResponseData>;
149
564
  getById: (id: number, options?: RequestOptions) => Promise<Invoice>;
@@ -219,4 +634,4 @@ declare function createOrvelloClient(config?: OrvelloClientConfig): OrvelloClien
219
634
 
220
635
  declare const CONTRACT_SHA256 = "4efd4e4b669168c9cab5419fa04dd4e26a2029de2d4b10a59918e366189e1072";
221
636
 
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 };
637
+ 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, 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 };