@ax-hub/sdk 0.3.0 → 1.0.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.ts CHANGED
@@ -124,6 +124,15 @@ declare class StreamConsumedError extends AxHubError {
124
124
  }
125
125
  declare class TenantSlugRequiredError extends AxHubError {
126
126
  }
127
+ /**
128
+ * SDK-self error: tenant-scoped app routes
129
+ * (`POST`/`GET /api/v1/tenants/{tenantID}/apps`) require a tenant **UUID** in
130
+ * the path. Thrown before any request when the SDK holds only a slug (or no
131
+ * tenant context). Mirrors {@link TenantSlugRequiredError}; constructed inline
132
+ * at call sites (crud.ts / scoped.ts), like TenantSlugRequiredError in client.ts.
133
+ */
134
+ declare class TenantIdRequiredError extends AxHubError {
135
+ }
127
136
  declare class ConfigurationError extends AxHubError {
128
137
  }
129
138
  declare class PoolStaleError extends UnauthenticatedError {
@@ -169,15 +178,24 @@ declare class DeviceFlowDeniedError extends AccessDeniedError {
169
178
  }
170
179
  declare class DeviceFlowTimeoutError extends ExpiredTokenError {
171
180
  }
172
-
173
- declare function isOAuthPath(path: string): boolean;
174
- interface DispatchContext {
175
- path: string;
176
- status: number;
177
- body: unknown;
178
- fallbackRequestId: string;
181
+ declare class InvalidTargetError extends OAuthError {
182
+ }
183
+ declare class InvalidClientError extends OAuthError {
184
+ }
185
+ declare class InvalidRequestError extends OAuthError {
186
+ }
187
+ declare class InvalidScopeError extends OAuthError {
188
+ }
189
+ declare class InvalidTokenError extends OAuthError {
190
+ }
191
+ declare class UnauthorizedClientError extends OAuthError {
192
+ }
193
+ declare class UnsupportedGrantTypeError extends OAuthError {
194
+ }
195
+ declare class OAuthServerError extends OAuthError {
196
+ }
197
+ declare class TemporarilyUnavailableError extends OAuthError {
179
198
  }
180
- declare function dispatch(ctx: DispatchContext): AxHubError;
181
199
 
182
200
  declare const brand: unique symbol;
183
201
  type Branded<T, B extends string> = T & {
@@ -305,6 +323,26 @@ declare class HttpClient {
305
323
  private logRequest;
306
324
  }
307
325
 
326
+ interface StaticTokenAuthOptions {
327
+ token: string;
328
+ tokenType: TokenType;
329
+ onRefresh?: () => Promise<string>;
330
+ }
331
+ declare class StaticTokenAuth implements AuthProvider {
332
+ private token;
333
+ readonly tokenType: TokenType;
334
+ private readonly onRefresh?;
335
+ private refreshing;
336
+ constructor(opts: StaticTokenAuthOptions);
337
+ currentToken(): string;
338
+ headersFor(ring: AuthRing): Record<string, string>;
339
+ onUnauthorized(): Promise<boolean>;
340
+ }
341
+ declare class NoAuth implements AuthProvider {
342
+ headersFor(_ring: AuthRing): Record<string, string>;
343
+ onUnauthorized(): Promise<boolean>;
344
+ }
345
+
308
346
  interface PaginatedList<T> {
309
347
  items: T[];
310
348
  nextCursor: string | null;
@@ -378,282 +416,59 @@ declare function decodeCursor(token: string): KeysetCursor;
378
416
  declare function orderByFingerprint(orderBy?: DataOrderBy): string;
379
417
  declare function cursorFromRow(row: Record<string, unknown> | undefined, opts?: CursorBuildOptions): string | null;
380
418
 
381
- interface RequestOptions {
419
+ interface ParsedFrame {
420
+ id?: string;
421
+ event?: string;
422
+ data: string;
423
+ }
424
+ type StreamItem<T> = {
425
+ type: 'item';
426
+ value: T;
427
+ id: string | undefined;
428
+ } | {
429
+ type: 'gap';
430
+ sinceId: string | undefined;
431
+ missingCount?: number;
432
+ } | {
433
+ type: 'decode-skip';
434
+ frame: ParsedFrame;
435
+ error: AxHubError;
436
+ };
437
+ interface SSEStreamOptions<T> {
438
+ url: string;
439
+ http: HttpClient;
440
+ ring: AuthRing;
382
441
  signal?: AbortSignal;
383
- timeoutMs?: number;
384
- idempotencyKey?: string | false;
442
+ maxReconnects?: number;
443
+ parseEvent: (frame: ParsedFrame) => T;
385
444
  }
386
- interface PageRequestOptions extends ListOptions, RequestOptions {
445
+ interface SSEStream<T> extends AsyncIterable<StreamItem<T>> {
446
+ dispose(): void;
387
447
  }
388
448
 
389
- interface AuditEvent {
390
- id: string;
391
- type?: string;
392
- actorId?: string;
393
- hash?: string;
394
- prevHash?: string;
395
- createdAt?: string;
396
- [key: string]: unknown;
397
- }
398
- interface EmitAuditEventInput {
399
- type: string;
400
- actorId?: string;
401
- resource?: string;
402
- payload?: unknown;
449
+ type WebhookVerifyReason = 'signature_mismatch' | 'timestamp_skew' | 'malformed_signature' | 'missing_secret' | 'replay';
450
+ interface VerifyWebhookInput {
451
+ rawBody: Buffer | Uint8Array | string;
452
+ signature: string;
453
+ secret: string;
454
+ tolerance?: number;
455
+ timestamp?: string;
456
+ replayCache?: Set<string>;
457
+ now?: () => number;
403
458
  }
404
- interface IntegrityCheckResult {
459
+ interface VerifyWebhookResult {
405
460
  ok: boolean;
406
- checked: number;
407
- firstBadSeq?: number;
408
- reason?: string;
409
- }
410
- interface AnonymizeInput {
411
- subjectId?: string;
412
- actorId?: string;
413
- anonymizedId?: string;
414
- reason?: string;
415
- }
416
- declare class AuditClient {
417
- private readonly http;
418
- readonly events: AuditEventsClient;
419
- readonly server: AuditServerClient;
420
- constructor(http: HttpClient);
421
- scoped(tenantSlug: string): TenantAuditClient;
422
- integrityCheck(tenantSlug: string, opts?: RequestOptions): Promise<IntegrityCheckResult>;
423
- anonymize(tenantSlug: string, input: AnonymizeInput, opts?: RequestOptions): Promise<AuditEvent | void>;
424
- }
425
- declare class TenantAuditClient {
426
- private readonly http;
427
- private readonly tenantSlug;
428
- readonly events: AuditEventsForTenantClient;
429
- readonly server: AuditServerForTenantClient;
430
- constructor(http: HttpClient, tenantSlug: string);
431
- integrityCheck(opts?: RequestOptions): Promise<IntegrityCheckResult>;
432
- anonymize(input: AnonymizeInput, opts?: RequestOptions): Promise<AuditEvent | void>;
433
- }
434
- declare class AuditEventsClient {
435
- private readonly http;
436
- constructor(http: HttpClient);
437
- forTenant(tenantSlug: string): AuditEventsForTenantClient;
438
- }
439
- declare class AuditEventsForTenantClient {
440
- private readonly http;
441
- private readonly tenantSlug;
442
- constructor(http: HttpClient, tenantSlug: string);
443
- list(opts?: PageRequestOptions & {
444
- type?: string;
445
- }): Promise<PaginatedList<AuditEvent>>;
446
- get(eventId: string, opts?: RequestOptions): Promise<AuditEvent>;
447
- }
448
- declare class AuditServerClient {
449
- private readonly http;
450
- constructor(http: HttpClient);
451
- forTenant(tenantSlug: string): AuditServerForTenantClient;
452
- }
453
- declare class AuditServerForTenantClient {
454
- private readonly http;
455
- private readonly tenantSlug;
456
- constructor(http: HttpClient, tenantSlug: string);
457
- /**
458
- * Emit a server-side audit event.
459
- *
460
- * @remarks The backend route `POST /audit-events/server` is not yet
461
- * implemented (currently 404). Retained ahead of backend support — see
462
- * ADR-0040. Do not rely on this in production until the route ships.
463
- */
464
- emit(input: EmitAuditEventInput, opts?: RequestOptions): Promise<AuditEvent>;
465
- }
466
-
467
- interface AuthzTag {
468
- id: string;
469
- name: string;
470
- parentId?: string;
471
- [key: string]: unknown;
472
- }
473
- interface AuthzSubject {
474
- id: string;
475
- type: string;
476
- externalId?: string;
477
- [key: string]: unknown;
478
- }
479
- interface AuthzGrant {
480
- id: string;
481
- subjectId: string;
482
- resource: string;
483
- action: string;
484
- effect: 'allow' | 'deny';
485
- [key: string]: unknown;
486
- }
487
- interface DecideInput {
488
- subjectId: string;
489
- resource: string;
490
- action: string;
491
- context?: Record<string, unknown>;
492
- }
493
- interface DecideResult {
494
- allowed: boolean;
495
- reason?: string;
496
- matchedGrantId?: string;
497
- }
498
- declare class AuthzClient {
499
- private readonly http;
500
- constructor(http: HttpClient);
501
- scoped(tenantSlug: string): TenantAuthzClient;
502
- }
503
- declare class TenantAuthzClient {
504
- /** @adminOnly Tag governance. `list()` requires tenant_admin (v0.1, SPEC 307) — member callers get ForbiddenError (no auto-retry; permission, not transient). Members browse the data catalog via `gateway.catalog`. */
505
- readonly tags: Crud<AuthzTag>;
506
- /** @adminOnly Subject governance. `list()` requires tenant_admin (v0.1) — member callers get ForbiddenError. */
507
- readonly subjects: Crud<AuthzSubject>;
508
- /** @adminOnly Grant governance. `list()` requires tenant_admin (v0.1) — member callers get ForbiddenError. */
509
- readonly grants: Crud<AuthzGrant>;
510
- readonly evaluator: AuthzEvaluatorClient;
511
- constructor(http: HttpClient, tenantSlug: string);
512
- }
513
- declare class Crud<T extends {
514
- id: string;
515
- }> {
516
- private readonly http;
517
- private readonly base;
518
- constructor(http: HttpClient, base: string);
519
- list(opts?: RequestOptions): Promise<T[]>;
520
- get(id: string, opts?: RequestOptions): Promise<T>;
521
- create(input: Record<string, unknown>, opts?: RequestOptions): Promise<T>;
522
- update(id: string, patch: Record<string, unknown>, opts?: RequestOptions): Promise<T>;
523
- delete(id: string, opts?: RequestOptions): Promise<void>;
524
- }
525
- declare class AuthzEvaluatorClient {
526
- private readonly http;
527
- private readonly base;
528
- private readonly ttlMs;
529
- private readonly cache;
530
- constructor(http: HttpClient, base: string, ttlMs?: number);
531
- decide(input: DecideInput, opts?: RequestOptions): Promise<DecideResult>;
532
- decideMany(inputs: DecideInput[], opts?: RequestOptions): Promise<DecideResult[]>;
461
+ reason?: WebhookVerifyReason;
533
462
  }
463
+ declare function signWebhook(rawBody: Buffer | Uint8Array | string, secret: string, timestamp?: string): string;
464
+ declare function verifyWebhook(input: VerifyWebhookInput): VerifyWebhookResult;
534
465
 
535
- interface Tenant {
536
- id: string;
537
- slug: string;
538
- name: string;
539
- plan?: string;
540
- createdAt?: string;
541
- updatedAt?: string;
542
- [key: string]: unknown;
543
- }
544
- interface CreateTenantInput {
545
- slug: string;
546
- name: string;
547
- plan?: string;
548
- }
549
- interface UpdateTenantInput {
550
- name?: string;
551
- plan?: string;
552
- }
553
- interface TenantMember {
554
- id: string;
555
- userId: string;
556
- role: string;
557
- status?: string;
558
- [key: string]: unknown;
559
- }
560
- interface TenantInvitation {
561
- id: string;
562
- email: string;
563
- role: string;
564
- status: string;
565
- reason?: string;
566
- [key: string]: unknown;
567
- }
568
- interface InviteTenantMemberInput {
569
- email: string;
570
- role: string;
571
- reason?: string;
572
- }
573
- interface BulkInviteResult {
574
- accepted: TenantInvitation[];
575
- rejected: Array<{
576
- email: string;
577
- reason: string;
578
- message?: string;
579
- }>;
580
- }
581
- interface EmailDomain {
582
- domain: string;
583
- verified?: boolean;
584
- [key: string]: unknown;
585
- }
586
- interface TenantIconUploadResult {
587
- uploadUrl: string;
588
- getUrl: string;
589
- expiresAt?: string;
590
- }
591
- declare class TenantsClient {
592
- private readonly http;
593
- constructor(http: HttpClient);
594
- scoped(tenantIdOrSlug: string): TenantScopedTenantsClient;
595
- create(input: CreateTenantInput, opts?: RequestOptions): Promise<Tenant>;
596
- list(opts?: PageRequestOptions): Promise<PaginatedList<Tenant>>;
597
- get(tenantIdOrSlug: string, opts?: RequestOptions): Promise<Tenant>;
598
- update(tenantIdOrSlug: string, patch: UpdateTenantInput, opts?: RequestOptions): Promise<Tenant>;
599
- delete(tenantIdOrSlug: string, opts?: RequestOptions): Promise<void>;
600
- signIconUploadURL(tenantIdOrSlug: string, input: {
601
- contentType: string;
602
- }, opts?: RequestOptions): Promise<TenantIconUploadResult>;
603
- get members(): TenantMembersClient;
604
- get invitations(): TenantInvitationsClient;
605
- get emailDomains(): TenantEmailDomainsClient;
606
- }
607
- declare class TenantScopedTenantsClient {
608
- readonly members: TenantMembersForTenantClient;
609
- readonly invitations: TenantInvitationsForTenantClient;
610
- readonly emailDomains: TenantEmailDomainsForTenantClient;
611
- constructor(http: HttpClient, tenantIdOrSlug: string);
612
- }
613
- declare class TenantMembersClient {
614
- private readonly http;
615
- constructor(http: HttpClient);
616
- forTenant(tenantIdOrSlug: string): TenantMembersForTenantClient;
617
- }
618
- declare class TenantMembersForTenantClient {
619
- private readonly http;
620
- private readonly tenant;
621
- constructor(http: HttpClient, tenant: string);
622
- list(opts?: PageRequestOptions): Promise<PaginatedList<TenantMember>>;
623
- update(membershipId: string, patch: {
624
- role?: string;
625
- }, opts?: RequestOptions): Promise<void>;
626
- deactivate(membershipId: string, opts?: RequestOptions): Promise<void>;
627
- reactivate(membershipId: string, opts?: RequestOptions): Promise<void>;
628
- }
629
- declare class TenantInvitationsClient {
630
- private readonly http;
631
- constructor(http: HttpClient);
632
- forTenant(tenantIdOrSlug: string): TenantInvitationsForTenantClient;
633
- }
634
- declare class TenantInvitationsForTenantClient {
635
- private readonly http;
636
- private readonly tenant;
637
- constructor(http: HttpClient, tenant: string);
638
- list(opts?: PageRequestOptions): Promise<PaginatedList<TenantInvitation>>;
639
- create(input: InviteTenantMemberInput, opts?: RequestOptions): Promise<TenantInvitation>;
640
- bulkCreate(inputs: InviteTenantMemberInput[], opts?: RequestOptions): Promise<BulkInviteResult>;
641
- delete(invitationId: string, opts?: RequestOptions): Promise<void>;
642
- }
643
- declare class TenantEmailDomainsClient {
644
- private readonly http;
645
- constructor(http: HttpClient);
646
- forTenant(tenantIdOrSlug: string): TenantEmailDomainsForTenantClient;
466
+ interface RequestOptions {
467
+ signal?: AbortSignal;
468
+ timeoutMs?: number;
469
+ idempotencyKey?: string | false;
647
470
  }
648
- declare class TenantEmailDomainsForTenantClient {
649
- private readonly http;
650
- private readonly tenant;
651
- constructor(http: HttpClient, tenant: string);
652
- list(opts?: RequestOptions): Promise<EmailDomain[]>;
653
- create(input: {
654
- domain: string;
655
- }, opts?: RequestOptions): Promise<EmailDomain>;
656
- delete(domain: string, opts?: RequestOptions): Promise<void>;
471
+ interface PageRequestOptions extends ListOptions, RequestOptions {
657
472
  }
658
473
 
659
474
  interface EnvVar {
@@ -675,16 +490,18 @@ declare class AppsEnvVarsMixin {
675
490
  listEnvVars(appId: string): Promise<EnvVar[]>;
676
491
  /**
677
492
  * Create or overwrite an env var. Key must match `^[A-Z_][A-Z0-9_]*$` —
678
- * validation happens client-side before any network round-trip.
493
+ * validation happens client-side before any network round-trip. `stage`
494
+ * scopes the value to a deploy stage (wire: `stage`); omit for the default.
679
495
  *
680
496
  * @example happy
681
497
  * await sdk.apps.setEnvVar('app_abc', 'DATABASE_URL', 'postgres://...')
498
+ * await sdk.apps.setEnvVar('app_abc', 'API_KEY', 'k', 'production')
682
499
  *
683
500
  * @example failure
684
501
  * try { await sdk.apps.setEnvVar('app_abc', 'database url', 'x') }
685
502
  * catch (e) { if (e instanceof ValidationError) /* fix key *\/ }
686
503
  */
687
- setEnvVar(appId: string, key: string, value: string): Promise<void>;
504
+ setEnvVar(appId: string, key: string, value: string, stage?: string): Promise<void>;
688
505
  /**
689
506
  * Fetch a single env var by key.
690
507
  *
@@ -707,6 +524,121 @@ declare class AppsEnvVarsMixin {
707
524
  deleteEnvVar(appId: string, key: string): Promise<void>;
708
525
  }
709
526
 
527
+ interface FieldAvailability {
528
+ available: boolean;
529
+ /** Set when `available` is false: `invalid` | `reserved` | `taken`. */
530
+ reason?: string;
531
+ }
532
+ interface AppAvailability {
533
+ slug?: FieldAvailability;
534
+ subdomain?: FieldAvailability;
535
+ }
536
+ interface CheckAvailabilityInput {
537
+ slug?: string;
538
+ subdomain?: string;
539
+ }
540
+ interface IconPreCreateInput {
541
+ /** MIME type of the asset, e.g. `image/png`. */
542
+ contentType: string;
543
+ /** Slug of the app-to-be; becomes the object key suffix. Must match the slug used at create. */
544
+ slug: string;
545
+ /** Icon variant. Defaults to `light`. */
546
+ variant?: 'light' | 'dark';
547
+ }
548
+ interface IconPreCreateResult {
549
+ /** Presigned PUT URL the caller uploads the binary to. Single-use, ~5 min. */
550
+ uploadUrl: string;
551
+ /** Public GET URL to set as `iconUrl`/`iconDarkUrl` on the subsequent create. */
552
+ getUrl: string;
553
+ expiresAt?: string;
554
+ }
555
+ declare class AppsAvailabilityMixin {
556
+ private readonly http;
557
+ private readonly defaultTenantId?;
558
+ constructor(http: HttpClient, defaultTenantId?: string | undefined);
559
+ private requireTenantId;
560
+ /**
561
+ * Check whether an app `slug` and/or `subdomain` is available before
562
+ * creating (member-gated). Tenant-scoped: requires `defaultTenantId`. Each
563
+ * returned field is present only when its input was supplied.
564
+ *
565
+ * @example happy
566
+ * const a = await sdk.apps.checkAvailability({ slug: 'my-app', subdomain: 'my' })
567
+ * if (a.slug?.available && a.subdomain?.available) /* safe to create *\/
568
+ *
569
+ * @example failure
570
+ * try { await sdk.apps.checkAvailability({ slug: 'x' }) }
571
+ * catch (e) { if (e instanceof TenantIdRequiredError) /* set defaultTenantId *\/ }
572
+ */
573
+ checkAvailability(input: CheckAvailabilityInput): Promise<AppAvailability>;
574
+ /**
575
+ * Get a presigned PUT URL for an app icon BEFORE the app is created
576
+ * (member-gated). Tenant-scoped: requires `defaultTenantId`. Use the
577
+ * returned `getUrl` as `iconUrl` (or `iconDarkUrl` for `variant: 'dark'`)
578
+ * when calling `apps.create`. Distinct from `apps.signIconUploadURL`, which
579
+ * targets an existing app.
580
+ *
581
+ * @example happy
582
+ * const { uploadUrl, getUrl } = await sdk.apps.iconPreCreateUrl({ contentType: 'image/png', slug: 'my-app' })
583
+ * await fetch(uploadUrl, { method: 'PUT', body: imageBlob, headers: { 'Content-Type': 'image/png' } })
584
+ * await sdk.apps.create({ slug: 'my-app', name: 'My App', iconUrl: getUrl })
585
+ *
586
+ * @example failure
587
+ * try { await sdk.apps.iconPreCreateUrl({ contentType: 'application/zip', slug: 'my-app' }) }
588
+ * catch (e) { if (e instanceof NotAllowedError) /* unsupported MIME *\/ }
589
+ */
590
+ iconPreCreateUrl(input: IconPreCreateInput): Promise<IconPreCreateResult>;
591
+ }
592
+
593
+ /**
594
+ * Resolves a tenant slug to its UUID for the apps control-ring
595
+ * (`/api/v1/tenants/{UUID}/apps`). A UUID passes through unchanged (no network
596
+ * call); a slug is mapped to its UUID via the caller's own memberships
597
+ * (`GET /api/v1/me` → `tenants[]`).
598
+ *
599
+ * The slug→UUID map is cached per resolver instance. One resolver is owned by
600
+ * the root {@link AxHubClient} and shared with `withTenant`-derived clients via
601
+ * the internal options, so a client tree fires `/me` at most once per distinct
602
+ * slug regardless of how many `sdk.apps` / `sdk.tenant(slug).apps` calls run.
603
+ */
604
+ declare class TenantResolver {
605
+ private readonly me;
606
+ private readonly cache;
607
+ constructor(http: HttpClient);
608
+ /**
609
+ * Returns the tenant UUID for `slugOrUuid`. A UUID is returned as-is (fast
610
+ * path, no `/me`). A slug is looked up in the caller's memberships, caching
611
+ * the result. Throws {@link TenantIdRequiredError} if the slug is not among
612
+ * the caller's tenants (the `/me` call itself succeeded — the slug is simply
613
+ * not a membership — so this is an SDK-self "couldn't resolve a tenant UUID"
614
+ * error, not a backend 404).
615
+ */
616
+ resolveTenantId(slugOrUuid: string, opts?: RequestOptions): Promise<string>;
617
+ }
618
+
619
+ type AppStatus = 'draft' | 'deployed' | 'archived' | 'active' | 'deleted' | 'permanently_deleted' | (string & {});
620
+ type AppVisibility = 'private' | 'tenant' | 'public' | 'invite_only' | (string & {});
621
+ type AppPublicationStatus = 'draft' | 'pending_review' | 'approved' | (string & {});
622
+ type AppReviewStatus = 'not_submitted' | 'pending' | 'approved' | 'rejected' | (string & {});
623
+ interface AppResponseCategory {
624
+ id: string;
625
+ tenantId?: string;
626
+ slug: string;
627
+ name: string;
628
+ description?: string;
629
+ color?: string;
630
+ iconUrl?: string;
631
+ displayOrder?: number;
632
+ appsCount?: number;
633
+ discoverableAppsCount?: number;
634
+ createdAt?: string;
635
+ updatedAt?: string;
636
+ }
637
+ interface AppResponseOwner {
638
+ id: string;
639
+ name?: string;
640
+ avatarUrl?: string;
641
+ }
710
642
  interface AppResponse {
711
643
  id: string;
712
644
  tenantId: string;
@@ -715,35 +647,113 @@ interface AppResponse {
715
647
  name: string;
716
648
  description?: string;
717
649
  iconUrl?: string;
650
+ iconDarkUrl?: string;
718
651
  schemaName: string;
719
- status: 'active' | 'deleted' | 'permanently_deleted';
720
- visibility: 'private' | 'tenant' | 'public';
721
- publicationStatus: 'draft' | 'pending_review' | 'approved';
652
+ status: AppStatus;
653
+ visibility: AppVisibility;
654
+ publicationStatus: AppPublicationStatus;
655
+ reviewStatus?: AppReviewStatus;
656
+ authMode?: string;
657
+ dataScopes?: string[];
658
+ deployMethod?: string;
659
+ resourceTier?: string;
660
+ subdomain?: string;
661
+ accessUrl?: string | null;
662
+ lastDeploymentStatus?: string | null;
663
+ operatingStatus?: string;
664
+ suspendedAt?: string | null;
665
+ resumedAt?: string | null;
666
+ categoryId?: string;
667
+ category?: AppResponseCategory;
668
+ owner?: AppResponseOwner;
722
669
  likeCount: number;
723
670
  subscriberCount: number;
671
+ callsCount?: number;
672
+ sharedTablesCount?: number;
724
673
  createdAt: string;
725
674
  updatedAt: string;
726
675
  deletedAt: string | null;
727
676
  }
677
+
678
+ type AppSort = '-created_at' | '-like_count' | '-subscriber_count' | 'name';
679
+ /**
680
+ * Filter/sort/page params for the tenant-scoped apps list
681
+ * (`GET /api/v1/tenants/{tenantID}/apps`). The `*In` fields accept an array and
682
+ * serialize to the comma-separated string the backend expects. Filtering is
683
+ * only honored on the tenant-scoped path. A tenant UUID (directly configured
684
+ * or resolved from the default tenant slug) is required; callers who want the
685
+ * self/workspace feed should use `sdk.apps.listMine()`.
686
+ */
687
+ interface ListAppsOptions extends ListOptions {
688
+ /** Free-text search. Wire: `q`. */
689
+ q?: string;
690
+ /** Wire: `category_id`. */
691
+ categoryId?: string;
692
+ /** Wire: `status`. */
693
+ status?: string;
694
+ /** CSV on the wire. Wire: `status_in`. */
695
+ statusIn?: string[];
696
+ /** Wire: `review_status`. */
697
+ reviewStatus?: string;
698
+ /** CSV on the wire. Wire: `review_status_in`. */
699
+ reviewStatusIn?: string[];
700
+ /** Wire: `operating_status`. */
701
+ operatingStatus?: string;
702
+ /** CSV on the wire. Wire: `operating_status_in`. */
703
+ operatingStatusIn?: string[];
704
+ /** Wire: `sort`. */
705
+ sort?: AppSort;
706
+ /** 1-based page number. Wire: `page`. */
707
+ page?: number;
708
+ /** Page size for offset pagination. Wire: `per_page`. */
709
+ perPage?: number;
710
+ }
728
711
  interface CreateAppInput {
729
712
  slug: string;
730
713
  name: string;
731
714
  description?: string;
732
715
  iconUrl?: string;
716
+ /** Dark-mode icon. Wire: `icon_dark_url`. */
717
+ iconDarkUrl?: string;
733
718
  visibility?: 'private' | 'tenant' | 'public';
719
+ /** Wire: `auth_mode`. */
720
+ authMode?: string;
721
+ /** Wire: `data_scopes`. */
722
+ dataScopes?: string[];
723
+ /** Wire: `deploy_method`. */
724
+ deployMethod?: string;
725
+ /** Wire: `resource_tier`. */
726
+ resourceTier?: string;
727
+ /** Wire: `subdomain`. */
728
+ subdomain?: string;
734
729
  }
735
730
  interface UpdateAppInput {
736
731
  name?: string;
737
732
  description?: string;
738
733
  iconUrl?: string;
734
+ /** Dark-mode icon. Wire: `icon_dark_url`. */
735
+ iconDarkUrl?: string;
739
736
  visibility?: 'private' | 'tenant' | 'public';
737
+ /** Wire: `auth_mode`. */
738
+ authMode?: string;
739
+ /** Wire: `data_scopes`. */
740
+ dataScopes?: string[];
741
+ /** Wire: `deploy_method`. */
742
+ deployMethod?: string;
743
+ /** Wire: `resource_tier`. */
744
+ resourceTier?: string;
745
+ /** Wire: `subdomain`. */
746
+ subdomain?: string;
747
+ /** Clear the app's subdomain. Wire: `clear_subdomain`. */
748
+ clearSubdomain?: boolean;
740
749
  }
741
750
  declare class AppsCrudMixin {
742
751
  private readonly http;
743
752
  private readonly defaultTenantSlug?;
744
753
  private readonly defaultTenantId?;
745
- constructor(http: HttpClient, defaultTenantSlug?: string | undefined, defaultTenantId?: string | undefined);
746
- private withTenantQuery;
754
+ private readonly tenantResolver?;
755
+ constructor(http: HttpClient, defaultTenantSlug?: string | undefined, defaultTenantId?: string | undefined, tenantResolver?: TenantResolver | undefined);
756
+ private resolveTenantId;
747
757
  /**
748
758
  * Create a new app in the caller's tenant.
749
759
  *
@@ -769,7 +779,7 @@ declare class AppsCrudMixin {
769
779
  * try { await sdk.apps.list() }
770
780
  * catch (e) { if (e instanceof PermissionDeniedError) /* request grant *\/ }
771
781
  */
772
- list(opts?: ListOptions): Promise<PaginatedList<AppResponse>>;
782
+ list(opts?: ListAppsOptions): Promise<PaginatedList<AppResponse>>;
773
783
  /**
774
784
  * Iterate every app across all pages. Yields each item; emits a
775
785
  * `{type:'drift', addedSince:N}` item if backend's total grows mid-scan.
@@ -952,19 +962,11 @@ interface AppCategory {
952
962
  description?: string;
953
963
  [key: string]: unknown;
954
964
  }
955
- interface CreateCategoryInput {
956
- slug: string;
957
- name: string;
958
- description?: string;
959
- }
960
965
  declare class AppsCategoriesMixin {
961
966
  private readonly http;
962
967
  constructor(http: HttpClient);
963
968
  list(tenantIdOrSlug: string, opts?: PageRequestOptions): Promise<PaginatedList<AppCategory>>;
964
- create(tenantIdOrSlug: string, input: CreateCategoryInput, opts?: RequestOptions): Promise<AppCategory>;
965
969
  get(tenantIdOrSlug: string, categoryId: string, opts?: RequestOptions): Promise<AppCategory>;
966
- update(tenantIdOrSlug: string, categoryId: string, patch: Partial<CreateCategoryInput>, opts?: RequestOptions): Promise<AppCategory>;
967
- delete(tenantIdOrSlug: string, categoryId: string, opts?: RequestOptions): Promise<void>;
968
970
  }
969
971
 
970
972
  interface Comment {
@@ -1035,11 +1037,50 @@ interface DiscoverAppsOptions extends PageRequestOptions {
1035
1037
  sort?: 'newest' | 'likes' | 'subscribers' | 'name';
1036
1038
  visibility?: 'private' | 'tenant' | 'public';
1037
1039
  }
1040
+ interface DiscoverFeedOptions {
1041
+ q?: string;
1042
+ category?: string;
1043
+ sort?: string;
1044
+ /** Only apps created within the last N days. */
1045
+ createdWithinDays?: number;
1046
+ /** 1-based page number. */
1047
+ page?: number;
1048
+ /** Apps per page. */
1049
+ perPage?: number;
1050
+ }
1038
1051
  declare class AppsDiscoverMixin {
1039
1052
  private readonly http;
1040
1053
  private readonly defaultTenantSlug?;
1041
- constructor(http: HttpClient, defaultTenantSlug?: string | undefined);
1054
+ private readonly defaultTenantId?;
1055
+ constructor(http: HttpClient, defaultTenantSlug?: string | undefined, defaultTenantId?: string | undefined);
1042
1056
  search(opts?: DiscoverAppsOptions): Promise<PaginatedList<AppResponse>>;
1057
+ private feedQuery;
1058
+ /**
1059
+ * Global curated discovery feed across all tenants the caller can see
1060
+ * (auth-only). Offset-paginated. Distinct from {@link search} (catalog
1061
+ * alias) — this is `GET /api/v1/apps/discover`.
1062
+ *
1063
+ * @example happy
1064
+ * const page = await sdk.apps.discoverGlobal({ sort: 'newest', perPage: 20 })
1065
+ * for (const a of page.items) console.log(a.slug)
1066
+ */
1067
+ discoverGlobal(opts?: DiscoverFeedOptions): Promise<PaginatedList<AppResponse>>;
1068
+ /**
1069
+ * Tenant-scoped discovery feed (member-gated). Requires a tenant UUID — set
1070
+ * `defaultTenantId` on the client. Backend route
1071
+ * `GET /api/v1/tenants/{tenantID}/discover/apps` parses `{tenantID}` as a
1072
+ * UUID; without it this throws `TenantIdRequiredError` before any request.
1073
+ *
1074
+ * @example happy
1075
+ * const page = await sdk.apps.discoverTenant({ sort: 'likes' })
1076
+ * for (const a of page.items) console.log(a.slug)
1077
+ *
1078
+ * @example failure
1079
+ * // No defaultTenantId set:
1080
+ * try { await sdk.apps.discoverTenant() }
1081
+ * catch (e) { if (e instanceof TenantIdRequiredError) /* set defaultTenantId *\/ }
1082
+ */
1083
+ discoverTenant(opts?: DiscoverFeedOptions): Promise<PaginatedList<AppResponse>>;
1043
1084
  }
1044
1085
 
1045
1086
  interface GitConnection {
@@ -1103,18 +1144,97 @@ declare class AppsGitMixin {
1103
1144
  */
1104
1145
  disconnect(appId: string): Promise<void>;
1105
1146
  /**
1106
- * Start the GitHub App installation OAuth flow. Returns a redirect URL the
1107
- * caller (typically a CLI / web flow) must open in a browser. After the user
1108
- * approves, GitHub posts back to AX Hub with the installation ID, which can
1109
- * then be used in `connect`.
1147
+ * Start the GitHub App installation OAuth flow. Returns a redirect URL the
1148
+ * caller (typically a CLI / web flow) must open in a browser. After the user
1149
+ * approves, GitHub posts back to AX Hub with the installation ID, which can
1150
+ * then be used in `connect`.
1151
+ *
1152
+ * @example happy
1153
+ * const { redirectUrl } = await sdk.apps.git.installStart('app_abc', {
1154
+ * redirectUri: 'http://localhost:3000/gh/callback',
1155
+ * })
1156
+ * open(redirectUrl)
1157
+ */
1158
+ installStart(appId: string, input?: InstallStartInput): Promise<GithubInstallStart>;
1159
+ }
1160
+
1161
+ interface AppInvitation {
1162
+ id: string;
1163
+ appId: string;
1164
+ userId: string;
1165
+ allowedScopes: string[];
1166
+ grantedAt: string;
1167
+ createdAt: string;
1168
+ }
1169
+ interface InviteUserInput {
1170
+ /** UUID of the target user. Must be an active member of the same tenant. */
1171
+ userId: string;
1172
+ }
1173
+ declare class AppsInvitationsMixin {
1174
+ private readonly http;
1175
+ constructor(http: HttpClient);
1176
+ /**
1177
+ * Invite a tenant member to an app (owner only). `userId` must be a UUID of
1178
+ * an active member of the same tenant; cross-tenant invites are rejected
1179
+ * (403). Inviting an existing member returns 409.
1180
+ *
1181
+ * @example happy
1182
+ * const inv = await sdk.apps.invitations.create('app_abc', { userId: '66666666-7777-8888-9999-aaaaaaaaaaaa' })
1183
+ * console.log(inv.userId, inv.allowedScopes)
1184
+ *
1185
+ * @example failure
1186
+ * try { await sdk.apps.invitations.create('app_abc', { userId: 'usr_dup' }) }
1187
+ * catch (e) {
1188
+ * if (e instanceof AlreadyMemberError) /* already invited *\/
1189
+ * if (e instanceof PermissionDeniedError) /* cross-tenant / not owner *\/
1190
+ * }
1191
+ */
1192
+ create(appId: string, input: InviteUserInput): Promise<AppInvitation>;
1193
+ /**
1194
+ * Revoke an app invitation by user UUID (owner only). Idempotent at the
1195
+ * transport level — backend returns 204 on success.
1196
+ *
1197
+ * @example happy
1198
+ * await sdk.apps.invitations.delete('app_abc', '66666666-7777-8888-9999-aaaaaaaaaaaa')
1199
+ *
1200
+ * @example failure
1201
+ * try { await sdk.apps.invitations.delete('app_abc', 'usr_missing') }
1202
+ * catch (e) { if (e instanceof NotFoundError) /* no such invitation *\/ }
1203
+ */
1204
+ delete(appId: string, userId: string): Promise<void>;
1205
+ }
1206
+
1207
+ declare class AppsLifecycleMixin {
1208
+ private readonly http;
1209
+ constructor(http: HttpClient);
1210
+ /**
1211
+ * Suspend an app (owner only). The app's dataapi stops serving traffic until
1212
+ * resumed. Suspending an already-suspended app returns 409
1213
+ * (`already_suspended`).
1214
+ *
1215
+ * @example happy
1216
+ * const app = await sdk.apps.suspend('app_abc')
1217
+ * console.log(app.status)
1218
+ *
1219
+ * @example failure
1220
+ * try { await sdk.apps.suspend('app_abc') }
1221
+ * catch (e) { if (e instanceof ConflictError) /* already suspended *\/ }
1222
+ */
1223
+ suspend(appId: string): Promise<AppResponse>;
1224
+ /**
1225
+ * Resume a suspended app (owner only). Resuming an app that is not suspended
1226
+ * returns 409 (`not_suspended`); an app that cannot be reactivated returns
1227
+ * 409 (`cannot_reactivate`).
1110
1228
  *
1111
1229
  * @example happy
1112
- * const { redirectUrl } = await sdk.apps.git.installStart('app_abc', {
1113
- * redirectUri: 'http://localhost:3000/gh/callback',
1114
- * })
1115
- * open(redirectUrl)
1230
+ * const app = await sdk.apps.resume('app_abc')
1231
+ * console.log(app.status)
1232
+ *
1233
+ * @example failure
1234
+ * try { await sdk.apps.resume('app_abc') }
1235
+ * catch (e) { if (e instanceof ConflictError) /* not suspended / cannot reactivate *\/ }
1116
1236
  */
1117
- installStart(appId: string, input?: InstallStartInput): Promise<GithubInstallStart>;
1237
+ resume(appId: string): Promise<AppResponse>;
1118
1238
  }
1119
1239
 
1120
1240
  interface LikeResult {
@@ -1155,6 +1275,60 @@ declare class AppsLikesMixin {
1155
1275
  me(appId: string): Promise<LikeStatus>;
1156
1276
  }
1157
1277
 
1278
+ interface AppMember {
1279
+ id: string;
1280
+ appId: string;
1281
+ userId: string;
1282
+ email?: string;
1283
+ allowedScopes: string[];
1284
+ grantedAt: string;
1285
+ grantedById?: string;
1286
+ }
1287
+ interface ListMembersOptions extends RequestOptions {
1288
+ /** 1-based page number. */
1289
+ page?: number;
1290
+ /** Members per page. */
1291
+ perPage?: number;
1292
+ }
1293
+ declare class AppsMembersMixin {
1294
+ private readonly http;
1295
+ constructor(http: HttpClient);
1296
+ /**
1297
+ * List members of an app (any member of the app can read). Offset-paginated.
1298
+ *
1299
+ * @example happy
1300
+ * const page = await sdk.apps.members.list('app_abc', { page: 1, perPage: 50 })
1301
+ * for (const m of page.items) console.log(m.userId, m.email, m.allowedScopes)
1302
+ *
1303
+ * @example failure
1304
+ * try { await sdk.apps.members.list('app_abc') }
1305
+ * catch (e) { if (e instanceof PermissionDeniedError) /* not a member *\/ }
1306
+ */
1307
+ list(appId: string, opts?: ListMembersOptions): Promise<PaginatedList<AppMember>>;
1308
+ }
1309
+
1310
+ declare class AppsMeMixin {
1311
+ private readonly http;
1312
+ constructor(http: HttpClient);
1313
+ /**
1314
+ * List apps the caller owns. Self-scoped via the auth principal.
1315
+ *
1316
+ * @example happy
1317
+ * const page = await sdk.apps.me.owned()
1318
+ * for (const a of page.items) console.log(a.slug)
1319
+ */
1320
+ owned(opts?: RequestOptions): Promise<PaginatedList<AppResponse>>;
1321
+ /**
1322
+ * List apps shared with (received by) the caller. Self-scoped via the auth
1323
+ * principal.
1324
+ *
1325
+ * @example happy
1326
+ * const page = await sdk.apps.me.received()
1327
+ * for (const a of page.items) console.log(a.slug)
1328
+ */
1329
+ received(opts?: RequestOptions): Promise<PaginatedList<AppResponse>>;
1330
+ }
1331
+
1158
1332
  interface OAuthClient {
1159
1333
  id: string;
1160
1334
  appId: string;
@@ -1181,6 +1355,11 @@ interface CreateOAuthClientInput {
1181
1355
  type?: 'public' | 'confidential';
1182
1356
  tokenEndpointAuthMethod?: 'client_secret_basic' | 'client_secret_post' | 'none';
1183
1357
  allowedGrantTypes?: string[];
1358
+ /**
1359
+ * RFC 8707 audience whitelist. Tokens issued to this client may only target
1360
+ * `resource` values in this list. Maps to wire `allowed_resources`.
1361
+ */
1362
+ allowedResources?: string[];
1184
1363
  }
1185
1364
  declare class AppsOAuthClientsMixin {
1186
1365
  private readonly http;
@@ -1321,6 +1500,8 @@ interface CreateTableInput {
1321
1500
  name: string;
1322
1501
  ownerColumn: string;
1323
1502
  columns: TableColumn[];
1503
+ /** Optional human-readable table description. Wire: `description`. */
1504
+ description?: string;
1324
1505
  }
1325
1506
  interface AddColumnInput {
1326
1507
  name: string;
@@ -1333,6 +1514,39 @@ interface AddGrantInput {
1333
1514
  principalId: string;
1334
1515
  scopes: GrantScope[];
1335
1516
  }
1517
+ interface TableAvailability {
1518
+ available: boolean;
1519
+ /** `ok` | `invalid_format` | `taken`. */
1520
+ reason: string;
1521
+ }
1522
+ interface ColumnTypeOption {
1523
+ /** API value to send (e.g. `text`). */
1524
+ value: string;
1525
+ /** Display label. */
1526
+ label: string;
1527
+ }
1528
+ interface TableRowColumn {
1529
+ name: string;
1530
+ type: string;
1531
+ nullable: boolean;
1532
+ }
1533
+ interface TableRowsMeta {
1534
+ page: number;
1535
+ perPage: number;
1536
+ total: number;
1537
+ totalPages: number;
1538
+ }
1539
+ interface TableRowsPage {
1540
+ columns: TableRowColumn[];
1541
+ rows: Array<Record<string, unknown>>;
1542
+ meta: TableRowsMeta;
1543
+ }
1544
+ interface BrowseRowsOptions extends RequestOptions {
1545
+ /** 1-based page number. */
1546
+ page?: number;
1547
+ /** Rows per page. */
1548
+ perPage?: number;
1549
+ }
1336
1550
  declare class AppsTablesMixin {
1337
1551
  private readonly http;
1338
1552
  constructor(http: HttpClient);
@@ -1432,6 +1646,38 @@ declare class AppsTablesMixin {
1432
1646
  * console.log(schema.indexes.map((i) => i.name))
1433
1647
  */
1434
1648
  inspect(appId: string, tableName: string): Promise<TableSchema>;
1649
+ /**
1650
+ * Check whether a table name is available before creating it (member-gated).
1651
+ * Validates name format client-side first.
1652
+ *
1653
+ * @example happy
1654
+ * const a = await sdk.apps.tables.checkAvailability('app_abc', 'orders')
1655
+ * if (a.available) /* safe to create *\/ else console.log(a.reason)
1656
+ */
1657
+ checkAvailability(appId: string, tableName: string): Promise<TableAvailability>;
1658
+ /**
1659
+ * List the supported column types for table-builder UIs (member-gated).
1660
+ *
1661
+ * @example happy
1662
+ * const types = await sdk.apps.tables.columnTypes('app_abc')
1663
+ * for (const t of types) console.log(t.value, t.label)
1664
+ */
1665
+ columnTypes(appId: string): Promise<ColumnTypeOption[]>;
1666
+ /**
1667
+ * Browse rows of a dynamic table (owner-gated admin view — owner_column is
1668
+ * ignored, all rows returned). Offset-paginated. For app-data access use the
1669
+ * data ring (`sdk.data.table(...)`) instead.
1670
+ *
1671
+ * @example happy
1672
+ * const page = await sdk.apps.tables.browseRows('app_abc', 'orders', { page: 1, perPage: 50 })
1673
+ * console.log(page.meta.totalPages, page.columns.map((c) => c.name))
1674
+ * for (const row of page.rows) console.log(row)
1675
+ *
1676
+ * @example failure
1677
+ * try { await sdk.apps.tables.browseRows('app_abc', 'missing') }
1678
+ * catch (e) { if (e instanceof NotFoundError) /* no such table *\/ }
1679
+ */
1680
+ browseRows(appId: string, tableName: string, opts?: BrowseRowsOptions): Promise<TableRowsPage>;
1435
1681
  }
1436
1682
 
1437
1683
  interface AppTemplate {
@@ -1450,9 +1696,14 @@ declare class AppsTemplatesMixin {
1450
1696
 
1451
1697
  declare class AppsClient {
1452
1698
  private readonly crud;
1699
+ private readonly lifecycle;
1700
+ private readonly availability;
1453
1701
  private readonly envVars;
1454
1702
  readonly publication: AppsPublicationMixin;
1455
1703
  readonly access: AppsAccessMixin;
1704
+ readonly invitations: AppsInvitationsMixin;
1705
+ readonly members: AppsMembersMixin;
1706
+ readonly me: AppsMeMixin;
1456
1707
  readonly categories: AppsCategoriesMixin;
1457
1708
  readonly discover: AppsDiscoverMixin;
1458
1709
  readonly likes: AppsLikesMixin;
@@ -1461,7 +1712,7 @@ declare class AppsClient {
1461
1712
  readonly git: AppsGitMixin;
1462
1713
  readonly tables: AppsTablesMixin;
1463
1714
  readonly templates: AppsTemplatesMixin;
1464
- constructor(http: HttpClient, defaultTenantSlug?: string, defaultTenantId?: string);
1715
+ constructor(http: HttpClient, defaultTenantSlug?: string, defaultTenantId?: string, tenantResolver?: TenantResolver);
1465
1716
  create: (...args: Parameters<AppsCrudMixin["create"]>) => Promise<AppResponse>;
1466
1717
  list: (...args: Parameters<AppsCrudMixin["list"]>) => Promise<PaginatedList<AppResponse>>;
1467
1718
  listAll: (...args: Parameters<AppsCrudMixin["listAll"]>) => AsyncGenerator<ListAllItem<AppResponse>, any, any>;
@@ -1473,15 +1724,19 @@ declare class AppsClient {
1473
1724
  signIconDarkUploadURL: (...args: Parameters<AppsCrudMixin["signIconDarkUploadURL"]>) => Promise<SignIconUploadResult>;
1474
1725
  /**
1475
1726
  * List apps the caller has been granted access to (not necessarily owned).
1476
- * Wraps `GET /users/me/apps`. Distinct from {@link list} which returns all
1477
- * apps in the resolved tenant; `listMine` is per-user scoped via the auth
1478
- * principal in the token.
1727
+ * Wraps `GET /api/v1/me/apps/workspace`. Distinct from {@link list} which
1728
+ * returns all apps in the resolved tenant; `listMine` is per-user scoped via
1729
+ * the auth principal in the token.
1479
1730
  *
1480
1731
  * @example happy
1481
1732
  * const accessible = await sdk.apps.listMine()
1482
1733
  * for (const a of accessible) console.log(a.slug)
1483
1734
  */
1484
1735
  listMine: (...args: Parameters<AppsCrudMixin["listMine"]>) => Promise<AppResponse[]>;
1736
+ suspend: (...args: Parameters<AppsLifecycleMixin["suspend"]>) => Promise<AppResponse>;
1737
+ resume: (...args: Parameters<AppsLifecycleMixin["resume"]>) => Promise<AppResponse>;
1738
+ checkAvailability: (...args: Parameters<AppsAvailabilityMixin["checkAvailability"]>) => Promise<AppAvailability>;
1739
+ iconPreCreateUrl: (...args: Parameters<AppsAvailabilityMixin["iconPreCreateUrl"]>) => Promise<IconPreCreateResult>;
1485
1740
  listEnvVars: (...args: Parameters<AppsEnvVarsMixin["listEnvVars"]>) => Promise<EnvVar[]>;
1486
1741
  setEnvVar: (...args: Parameters<AppsEnvVarsMixin["setEnvVar"]>) => Promise<void>;
1487
1742
  getEnvVar: (...args: Parameters<AppsEnvVarsMixin["getEnvVar"]>) => Promise<EnvVar>;
@@ -1734,17 +1989,15 @@ declare class TenantScopedClient {
1734
1989
  readonly slug: string;
1735
1990
  private readonly root;
1736
1991
  readonly apps: TenantScopedAppsClient;
1737
- constructor(slug: string, scopedRoot: AxHubClient, root: AxHubClient);
1738
- get tenants(): TenantScopedTenantsClient;
1739
- get authz(): TenantAuthzClient;
1740
- get audit(): TenantAuditClient;
1992
+ constructor(slug: string, scopedRoot: AxHubClient, root: AxHubClient, tenantResolver: TenantResolver);
1741
1993
  get gateway(): TenantGatewayClient;
1742
1994
  app(appSlug: string): AppScopedClient;
1743
1995
  }
1744
1996
  declare class TenantScopedAppsClient {
1745
1997
  private readonly tenantSlug;
1746
1998
  private readonly http;
1747
- constructor(tenantSlug: string, http: HttpClient);
1999
+ private readonly tenantResolver;
2000
+ constructor(tenantSlug: string, http: HttpClient, tenantResolver: TenantResolver);
1748
2001
  create(input: CreateAppInput, opts?: RequestOptions): Promise<AppResponse>;
1749
2002
  list(opts?: PageRequestOptions): Promise<PaginatedList<AppResponse>>;
1750
2003
  listAll(opts?: PageRequestOptions): AsyncGenerator<ListAllItem<AppResponse>>;
@@ -1806,9 +2059,92 @@ interface CreateDeploymentInput {
1806
2059
  /** Force a rebuild even if this commit already has a built image (dependency / base-image refresh). */
1807
2060
  forceRebuild?: boolean;
1808
2061
  }
2062
+ interface LogLine {
2063
+ /** RFC3339 timestamp the line was emitted. */
2064
+ ts: string;
2065
+ /** Container that produced the line (compose multi-service). */
2066
+ container: string;
2067
+ /** One stdout/stderr line (JSON string if structured). */
2068
+ message: string;
2069
+ /** Unique key for de-duplication. */
2070
+ insertId: string;
2071
+ }
2072
+ interface LogsPage {
2073
+ lines: LogLine[];
2074
+ /** Pass back as `cursor` to continue; empty string means end. */
2075
+ nextCursor: string;
2076
+ hasMore: boolean;
2077
+ }
2078
+ interface FetchLogsOptions {
2079
+ /** `forward` (newer) or `backward` (older). */
2080
+ direction?: 'forward' | 'backward';
2081
+ /** Opaque cursor from a prior `nextCursor`. */
2082
+ cursor?: string;
2083
+ /** RFC3339 lower bound. */
2084
+ since?: string;
2085
+ /** RFC3339 upper bound. */
2086
+ until?: string;
2087
+ /** Max lines per page. */
2088
+ limit?: number;
2089
+ }
2090
+ interface StartBootstrapInput {
2091
+ name: string;
2092
+ slug: string;
2093
+ subdomain: string;
2094
+ templateId: string;
2095
+ githubInstallationId: number;
2096
+ githubOwner: string;
2097
+ repoName: string;
2098
+ repoPrivate?: boolean;
2099
+ }
2100
+ interface BootstrapAccepted {
2101
+ /** Saga id to poll with `bootstrapStatus`. */
2102
+ bootstrapId: string;
2103
+ /** Polling endpoint path. */
2104
+ statusUrl: string;
2105
+ }
2106
+ type BootstrapStage = 'app' | 'repo' | 'push' | 'connect' | 'deploy' | 'done';
2107
+ type BootstrapStatusValue = 'running' | 'done' | 'failed';
2108
+ interface BootstrapStatus {
2109
+ id: string;
2110
+ stage: string;
2111
+ status: string;
2112
+ appId?: string;
2113
+ deploymentId?: string;
2114
+ repoFullName?: string;
2115
+ errorCode?: string;
2116
+ errorMessage?: string;
2117
+ }
2118
+ interface GithubAccount {
2119
+ login: string;
2120
+ type: string;
2121
+ installed: boolean;
2122
+ installationId?: number;
2123
+ avatarUrl?: string;
2124
+ installUrl?: string;
2125
+ }
2126
+ interface GithubRepo {
2127
+ id: number;
2128
+ name: string;
2129
+ fullName: string;
2130
+ private: boolean;
2131
+ defaultBranch: string;
2132
+ }
2133
+ interface GithubReposPage {
2134
+ repositories: GithubRepo[];
2135
+ /** Total repos before pagination. */
2136
+ totalCount: number;
2137
+ }
2138
+ interface ListReposOptions {
2139
+ /** 1-based page number. */
2140
+ page?: number;
2141
+ /** Repos per page. */
2142
+ perPage?: number;
2143
+ }
1809
2144
  declare class DeploymentsClient {
1810
2145
  private readonly http;
1811
- constructor(http: HttpClient);
2146
+ private readonly defaultTenantId?;
2147
+ constructor(http: HttpClient, defaultTenantId?: string | undefined);
1812
2148
  /**
1813
2149
  * Trigger a new deployment. Returns immediately with the deployment row
1814
2150
  * in `pending` or `building` state; poll `get()` to observe progression.
@@ -1866,6 +2202,75 @@ declare class DeploymentsClient {
1866
2202
  * }
1867
2203
  */
1868
2204
  rollback(appId: string, did: string): Promise<void>;
2205
+ /**
2206
+ * Fetch runtime logs for an app's running containers (owner-gated). Cursor
2207
+ * paginated: pass the returned `nextCursor` back to continue. `forward`
2208
+ * fetches newer lines (poll loop); `backward` fetches older history.
2209
+ *
2210
+ * @example happy
2211
+ * let page = await sdk.deployments.logs('app_abc', { direction: 'backward', limit: 100 })
2212
+ * for (const l of page.lines) console.log(l.ts, l.message)
2213
+ * if (page.hasMore) page = await sdk.deployments.logs('app_abc', { cursor: page.nextCursor })
2214
+ *
2215
+ * @example failure
2216
+ * try { await sdk.deployments.logs('app_abc') }
2217
+ * catch (e) { if (e instanceof UnavailableError) /* log backend down (503) *\/ }
2218
+ */
2219
+ logs(appId: string, opts?: FetchLogsOptions): Promise<LogsPage>;
2220
+ private requireTenantId;
2221
+ /**
2222
+ * Start an app-bootstrap saga (member-gated): create a GitHub repo from a
2223
+ * template, connect it, and deploy in one async flow. Returns immediately
2224
+ * (202) with a `bootstrapId` — poll `bootstrapStatus` to observe progress.
2225
+ * Tenant-scoped: requires `defaultTenantId`.
2226
+ *
2227
+ * @example happy
2228
+ * const { bootstrapId } = await sdk.deployments.startBootstrap({
2229
+ * name: 'My Todo', slug: 'my-todo', subdomain: 'todo',
2230
+ * templateId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
2231
+ * githubInstallationId: 12345678, githubOwner: 'ksro0128', repoName: 'my-todo-frontend',
2232
+ * })
2233
+ *
2234
+ * @example failure
2235
+ * try { await sdk.deployments.startBootstrap({ ...input }) }
2236
+ * catch (e) { if (e instanceof TenantIdRequiredError) /* set defaultTenantId *\/ }
2237
+ */
2238
+ startBootstrap(input: StartBootstrapInput): Promise<BootstrapAccepted>;
2239
+ /**
2240
+ * Poll the status of an app-bootstrap saga (member-gated). Tenant-scoped:
2241
+ * requires `defaultTenantId`. `status` is `running` | `done` | `failed`;
2242
+ * `stage` walks `app → repo → push → connect → deploy → done`.
2243
+ *
2244
+ * @example happy
2245
+ * const st = await sdk.deployments.bootstrapStatus('bs_a1b2c3d4')
2246
+ * if (st.status === 'done') console.log(st.appId, st.deploymentId)
2247
+ * else if (st.status === 'failed') console.error(st.errorCode, st.errorMessage)
2248
+ */
2249
+ bootstrapStatus(bootstrapId: string): Promise<BootstrapStatus>;
2250
+ /**
2251
+ * List GitHub accounts (user + orgs) visible to the caller and whether the
2252
+ * axhub GitHub App is installed on each (auth-only). Use the
2253
+ * `installationId` of an installed account to list its repos.
2254
+ *
2255
+ * @example happy
2256
+ * const accounts = await sdk.deployments.githubAccounts()
2257
+ * for (const a of accounts) console.log(a.login, a.installed, a.installationId)
2258
+ *
2259
+ * @example failure
2260
+ * try { await sdk.deployments.githubAccounts() }
2261
+ * catch (e) { if (e instanceof PreconditionFailedError) /* GitHub link required (428) *\/ }
2262
+ */
2263
+ githubAccounts(): Promise<GithubAccount[]>;
2264
+ /**
2265
+ * List repositories under a GitHub installation (auth-only). Offset
2266
+ * paginated. Get the `installationId` from `githubAccounts`.
2267
+ *
2268
+ * @example happy
2269
+ * const page = await sdk.deployments.githubRepos(12345678, { page: 1, perPage: 30 })
2270
+ * console.log(page.totalCount)
2271
+ * for (const r of page.repositories) console.log(r.fullName, r.defaultBranch)
2272
+ */
2273
+ githubRepos(installationId: number, opts?: ListReposOptions): Promise<GithubReposPage>;
1869
2274
  }
1870
2275
 
1871
2276
  interface GatewayQueryInput {
@@ -1987,10 +2392,28 @@ interface InvokeResult<Row = Record<string, unknown>> {
1987
2392
  rowCount: number;
1988
2393
  matchedPolicies?: string[];
1989
2394
  }
2395
+ interface EngineCapability {
2396
+ engine: string;
2397
+ kind: string;
2398
+ displayName: string;
2399
+ supportedActions: string[];
2400
+ /** Per-action allowed effects (action → effect[]). */
2401
+ allowedEffects: Record<string, string[]>;
2402
+ }
1990
2403
  declare class GatewayClient {
1991
2404
  private readonly http;
1992
2405
  constructor(http: HttpClient);
1993
2406
  scoped(tenantSlug: string): TenantGatewayClient;
2407
+ /**
2408
+ * List the gateway's engine capabilities (auth-only; no tenant membership
2409
+ * required). Each entry describes an engine + kind, its invokable actions,
2410
+ * and the effects each action may produce. Tenant-independent.
2411
+ *
2412
+ * @example happy
2413
+ * const engines = await sdk.gateway.engines()
2414
+ * for (const e of engines) console.log(e.engine, e.kind, e.supportedActions)
2415
+ */
2416
+ engines(opts?: RequestOptions): Promise<EngineCapability[]>;
1994
2417
  }
1995
2418
  declare class TenantGatewayClient {
1996
2419
  /** Run a parameterized read query. Member OK. See also `catalog.invoke()`. */
@@ -2124,6 +2547,36 @@ interface DeviceAuthorizationResponse {
2124
2547
  interval: number;
2125
2548
  raw: Record<string, unknown>;
2126
2549
  }
2550
+ /**
2551
+ * RFC 7591 Dynamic Client Registration request for an MCP client. All fields
2552
+ * optional per the spec; the backend fills defaults. `resource`/`resources`
2553
+ * are the RFC 8707 audiences the client may request.
2554
+ */
2555
+ interface RegisterMcpClientInput {
2556
+ clientName?: string;
2557
+ clientUri?: string;
2558
+ redirectUris?: string[];
2559
+ grantTypes?: string[];
2560
+ responseTypes?: string[];
2561
+ scope?: string;
2562
+ tokenEndpointAuthMethod?: string;
2563
+ resource?: string;
2564
+ resources?: string[];
2565
+ softwareId?: string;
2566
+ softwareVersion?: string;
2567
+ }
2568
+ /** RFC 7591 registration response. Mirrors backend `dynamicRegistrationResponse`. */
2569
+ interface RegisterMcpClientResult {
2570
+ clientId: string;
2571
+ clientIdIssuedAt?: number;
2572
+ clientName?: string;
2573
+ redirectUris?: string[];
2574
+ grantTypes?: string[];
2575
+ responseTypes?: string[];
2576
+ scope?: string;
2577
+ tokenEndpointAuthMethod?: string;
2578
+ raw: Record<string, unknown>;
2579
+ }
2127
2580
  interface IdentityProvider {
2128
2581
  id: string;
2129
2582
  tenantId?: string;
@@ -2148,7 +2601,6 @@ declare class IdentityClient {
2148
2601
  readonly oauth: IdentityOAuthClient;
2149
2602
  readonly oidc: IdentityOIDCClient;
2150
2603
  readonly deviceCode: IdentityDeviceCodeClient;
2151
- readonly idp: IdentityProviderClient;
2152
2604
  readonly systemOAuthClients: IdentitySystemOAuthClientsClient;
2153
2605
  constructor(http: HttpClient, defaultTenantSlug?: string);
2154
2606
  /** @deprecated Use sdk.identity.pat.issue(). Kept until 1.0 RC migration. */
@@ -2178,6 +2630,10 @@ declare class IdentityOAuthClient {
2178
2630
  private readonly defaultTenantSlug?;
2179
2631
  constructor(http: HttpClient, defaultTenantSlug?: string | undefined);
2180
2632
  private tenantQuery;
2633
+ /**
2634
+ * Build the `/oauth/authorize` URL. `resource` is the RFC 8707 audience —
2635
+ * pass the target API's identifier to bind the issued token to it.
2636
+ */
2181
2637
  authorizeUrl(input: {
2182
2638
  clientId: string;
2183
2639
  redirectUri: string;
@@ -2185,6 +2641,7 @@ declare class IdentityOAuthClient {
2185
2641
  state?: string;
2186
2642
  codeChallenge?: string;
2187
2643
  codeChallengeMethod?: string;
2644
+ resource?: string;
2188
2645
  }): string;
2189
2646
  exchangeCode(input: {
2190
2647
  code: string;
@@ -2192,11 +2649,13 @@ declare class IdentityOAuthClient {
2192
2649
  redirectUri: string;
2193
2650
  codeVerifier: string;
2194
2651
  clientSecret?: string;
2652
+ resource?: string;
2195
2653
  }, opts?: RequestOptions): Promise<OAuthTokenResponse>;
2196
2654
  refreshTokens(input: {
2197
2655
  refreshToken: string;
2198
2656
  clientId?: string;
2199
2657
  clientSecret?: string;
2658
+ resource?: string;
2200
2659
  }, opts?: RequestOptions): Promise<OAuthTokenResponse>;
2201
2660
  revoke(input: {
2202
2661
  token: string;
@@ -2204,6 +2663,25 @@ declare class IdentityOAuthClient {
2204
2663
  clientId?: string;
2205
2664
  }, opts?: RequestOptions): Promise<void>;
2206
2665
  userinfo(opts?: RequestOptions): Promise<Record<string, unknown>>;
2666
+ /**
2667
+ * RFC 7591 Dynamic Client Registration for an MCP client. This route is
2668
+ * **unauthenticated** (`POST /oauth/register`, public ring) — no token is
2669
+ * sent. The returned `clientId` (and any backend-issued secret in `raw`) is
2670
+ * the registration result; persist it on the agent side.
2671
+ *
2672
+ * @example happy
2673
+ * const reg = await sdk.identity.oauth.registerMcpClient({
2674
+ * clientName: 'my-mcp-agent',
2675
+ * redirectUris: ['https://agent.example/cb'],
2676
+ * resource: 'https://api.example/mcp',
2677
+ * })
2678
+ * storeClientId(reg.clientId)
2679
+ *
2680
+ * @example failure
2681
+ * try { await sdk.identity.oauth.registerMcpClient({ redirectUris: ['not-a-url'] }) }
2682
+ * catch (e) { if (e instanceof OAuthError) /* invalid_redirect_uri / invalid_client_metadata *\/ }
2683
+ */
2684
+ registerMcpClient(input: RegisterMcpClientInput, opts?: RequestOptions): Promise<RegisterMcpClientResult>;
2207
2685
  getClient(clientId: string, opts?: RequestOptions): Promise<SystemOAuthClient>;
2208
2686
  revokeOwnGrant(clientId: string, opts?: RequestOptions): Promise<void>;
2209
2687
  }
@@ -2215,15 +2693,63 @@ declare class IdentityOIDCClient {
2215
2693
  discovery(opts?: RequestOptions): Promise<Record<string, unknown>>;
2216
2694
  jwks(opts?: RequestOptions): Promise<Record<string, unknown>>;
2217
2695
  providers(opts?: RequestOptions): Promise<IdentityProvider[]>;
2696
+ /**
2697
+ * Resolve the interactive IdP login start URL. `returnOrigin` (RFC: the SPA
2698
+ * origin the backend bounces the browser back to after the IdP round-trip)
2699
+ * maps to the `return_origin` query param on `GET /auth/{providerID}/start`.
2700
+ */
2218
2701
  startURL(providerId: string, input?: {
2219
2702
  redirectTo?: string;
2220
2703
  state?: string;
2704
+ returnOrigin?: string;
2221
2705
  }, opts?: RequestOptions): Promise<string>;
2706
+ /**
2707
+ * Build the Google OAuth login start URL (`GET /auth/google_oauth2/start`,
2708
+ * legacy interactive route). Issues a 302 to Google, so this is a URL the
2709
+ * caller navigates the browser to. `returnTo` / `returnOrigin` map to the
2710
+ * `return_to` / `return_origin` query params the backend reads to bounce the
2711
+ * browser back after the Google round-trip.
2712
+ *
2713
+ * @example happy
2714
+ * const url = sdk.identity.oidc.googleStartUrl({ returnTo: 'https://app.example/done' })
2715
+ * window.location.href = url
2716
+ */
2717
+ googleStartUrl(input?: {
2718
+ returnTo?: string;
2719
+ returnOrigin?: string;
2720
+ }): string;
2222
2721
  exchangeCallback(input: {
2223
2722
  code: string;
2224
2723
  state?: string;
2225
2724
  provider?: string;
2226
2725
  }, opts?: RequestOptions): Promise<OAuthTokenResponse>;
2726
+ /**
2727
+ * Build the GitHub OAuth start URL. `GET /auth/github` issues a 302 redirect
2728
+ * to GitHub, so this is a URL the caller navigates the browser to (it does
2729
+ * not return JSON). `returnTo` is where the backend sends the browser back
2730
+ * after the GitHub round-trip completes.
2731
+ *
2732
+ * @example happy
2733
+ * const url = sdk.identity.oidc.githubStartUrl({ returnTo: 'https://app.example/done' })
2734
+ * window.location.href = url
2735
+ */
2736
+ githubStartUrl(input?: {
2737
+ returnTo?: string;
2738
+ }): string;
2739
+ /**
2740
+ * Build the GitHub OAuth callback URL. `GET /auth/github/callback` also
2741
+ * 302-redirects (the backend sets the session and bounces the browser to
2742
+ * `return_to`), so this is a URL helper, not a JSON-returning request — the
2743
+ * browser hits it directly with GitHub's `code`/`state` query params.
2744
+ *
2745
+ * @example happy
2746
+ * const url = sdk.identity.oidc.githubCallbackUrl({ code: 'gh_code', state: 'xyz' })
2747
+ */
2748
+ githubCallbackUrl(input: {
2749
+ code?: string;
2750
+ state?: string;
2751
+ error?: string;
2752
+ }): string;
2227
2753
  }
2228
2754
  declare class IdentityDeviceCodeClient {
2229
2755
  private readonly http;
@@ -2241,14 +2767,6 @@ declare class IdentityDeviceCodeClient {
2241
2767
  signal?: AbortSignal;
2242
2768
  }, opts?: RequestOptions): Promise<OAuthTokenResponse>;
2243
2769
  }
2244
- declare class IdentityProviderClient {
2245
- private readonly http;
2246
- constructor(http: HttpClient);
2247
- list(tenantId: string, opts?: RequestOptions): Promise<IdentityProvider[]>;
2248
- create(tenantId: string, input: Record<string, unknown>, opts?: RequestOptions): Promise<IdentityProvider>;
2249
- enable(tenantId: string, providerId: string, opts?: RequestOptions): Promise<IdentityProvider>;
2250
- disable(tenantId: string, providerId: string, opts?: RequestOptions): Promise<IdentityProvider>;
2251
- }
2252
2770
  declare class IdentitySystemOAuthClientsClient {
2253
2771
  private readonly http;
2254
2772
  constructor(http: HttpClient);
@@ -2323,6 +2841,59 @@ declare class PublicationRequestsClient {
2323
2841
  * catch (e) { if (e instanceof NotAdminError) /* not platform admin *\/ }
2324
2842
  */
2325
2843
  listPending(opts?: ListOptions): Promise<PaginatedList<PublicationRequest>>;
2844
+ /**
2845
+ * List settled (approved/rejected) publication requests for a tenant
2846
+ * (reviewer-gated). `tenantId` is required by the backend route — passing it
2847
+ * empty throws `RequiredError` before any request.
2848
+ *
2849
+ * @example happy
2850
+ * const page = await sdk.publicationRequests.history('tnt_1', { pageSize: 20 })
2851
+ * for (const pr of page.items) console.log(pr.appId, pr.status)
2852
+ *
2853
+ * @example failure
2854
+ * try { await sdk.publicationRequests.history('') }
2855
+ * catch (e) { if (e instanceof RequiredError) /* tenantId required *\/ }
2856
+ */
2857
+ history(tenantId: string, opts?: ListOptions): Promise<PaginatedList<PublicationRequest>>;
2858
+ }
2859
+
2860
+ interface Tenant {
2861
+ id: string;
2862
+ slug: string;
2863
+ name: string;
2864
+ plan?: string;
2865
+ createdAt?: string;
2866
+ updatedAt?: string;
2867
+ [key: string]: unknown;
2868
+ }
2869
+ declare class TenantsClient {
2870
+ private readonly http;
2871
+ constructor(http: HttpClient);
2872
+ get(tenantIdOrSlug: string, opts?: RequestOptions): Promise<Tenant>;
2873
+ }
2874
+
2875
+ interface PublicConfig {
2876
+ /** Base domain apps are served under, e.g. `axhub.jocodingax.ai`. */
2877
+ baseDomain: string;
2878
+ /** Any additional fields the backend adds are passed through. */
2879
+ [key: string]: unknown;
2880
+ }
2881
+ declare class ConfigClient {
2882
+ private readonly http;
2883
+ constructor(http: HttpClient);
2884
+ /**
2885
+ * Fetch public runtime config (tokenless). No Authorization header is sent;
2886
+ * usable before login. Rate-limited (429) if hammered.
2887
+ *
2888
+ * @example happy
2889
+ * const cfg = await sdk.config.public()
2890
+ * console.log(cfg.baseDomain)
2891
+ *
2892
+ * @example failure
2893
+ * try { await sdk.config.public() }
2894
+ * catch (e) { if (e instanceof RateLimitedError) /* back off (429) *\/ }
2895
+ */
2896
+ public(opts?: RequestOptions): Promise<PublicConfig>;
2326
2897
  }
2327
2898
 
2328
2899
  interface MockClientOptions {
@@ -2373,6 +2944,7 @@ interface AxHubInternalOptions {
2373
2944
  logger: Logger;
2374
2945
  schemaCacheOptions?: SchemaCacheOptions;
2375
2946
  mockStore?: MockStore;
2947
+ tenantResolver?: TenantResolver;
2376
2948
  }
2377
2949
  declare class AxHubClient {
2378
2950
  readonly http: HttpClient;
@@ -2381,22 +2953,25 @@ declare class AxHubClient {
2381
2953
  readonly logger: Logger;
2382
2954
  private readonly schemaCacheOptions?;
2383
2955
  readonly mock?: MockStore;
2956
+ private readonly tenantResolver;
2384
2957
  private _apps?;
2385
- private _audit?;
2386
- private _authz?;
2387
2958
  private _data?;
2388
2959
  private _deployments?;
2389
2960
  private _gateway?;
2390
2961
  private _identity?;
2391
2962
  private _publicationRequests?;
2392
2963
  private _tenants?;
2964
+ private _config?;
2393
2965
  constructor(opts: AxHubClientOptions | AxHubInternalOptions);
2394
2966
  resolveTenantSlug(perCall?: string): string;
2395
2967
  get apps(): AppsClient;
2396
- get audit(): AuditClient;
2397
- get authz(): AuthzClient;
2398
2968
  get data(): DataClient;
2399
2969
  get deployments(): DeploymentsClient;
2970
+ /**
2971
+ * Public, tokenless configuration (`sdk.config.public()`). No Authorization
2972
+ * header is sent — usable before authentication.
2973
+ */
2974
+ get config(): ConfigClient;
2400
2975
  get gateway(): GatewayClient;
2401
2976
  get identity(): IdentityClient;
2402
2977
  get tenants(): TenantsClient;
@@ -2442,63 +3017,4 @@ declare class AxHubClient {
2442
3017
  tenant(tenantSlug: string): TenantScopedClient;
2443
3018
  }
2444
3019
 
2445
- interface StaticTokenAuthOptions {
2446
- token: string;
2447
- tokenType: TokenType;
2448
- onRefresh?: () => Promise<string>;
2449
- }
2450
- declare class StaticTokenAuth implements AuthProvider {
2451
- private token;
2452
- readonly tokenType: TokenType;
2453
- private readonly onRefresh?;
2454
- private refreshing;
2455
- constructor(opts: StaticTokenAuthOptions);
2456
- currentToken(): string;
2457
- headersFor(ring: AuthRing): Record<string, string>;
2458
- onUnauthorized(): Promise<boolean>;
2459
- }
2460
- declare class NoAuth implements AuthProvider {
2461
- headersFor(_ring: AuthRing): Record<string, string>;
2462
- onUnauthorized(): Promise<boolean>;
2463
- }
2464
-
2465
- interface ParsedFrame {
2466
- id?: string;
2467
- event?: string;
2468
- data: string;
2469
- }
2470
- type StreamItem<T> = {
2471
- type: 'item';
2472
- value: T;
2473
- id: string | undefined;
2474
- } | {
2475
- type: 'gap';
2476
- sinceId: string | undefined;
2477
- missingCount?: number;
2478
- } | {
2479
- type: 'decode-skip';
2480
- frame: ParsedFrame;
2481
- error: AxHubError;
2482
- };
2483
- interface SSEStream<T> extends AsyncIterable<StreamItem<T>> {
2484
- dispose(): void;
2485
- }
2486
-
2487
- type WebhookVerifyReason = 'signature_mismatch' | 'timestamp_skew' | 'malformed_signature' | 'missing_secret' | 'replay';
2488
- interface VerifyWebhookInput {
2489
- rawBody: Buffer | Uint8Array | string;
2490
- signature: string;
2491
- secret: string;
2492
- tolerance?: number;
2493
- timestamp?: string;
2494
- replayCache?: Set<string>;
2495
- now?: () => number;
2496
- }
2497
- interface VerifyWebhookResult {
2498
- ok: boolean;
2499
- reason?: WebhookVerifyReason;
2500
- }
2501
- declare function signWebhook(rawBody: Buffer | Uint8Array | string, secret: string, timestamp?: string): string;
2502
- declare function verifyWebhook(input: VerifyWebhookInput): VerifyWebhookResult;
2503
-
2504
- export { AbortError, AccessDeniedError, type AddColumnInput, type AddCommentInput, type AddGrantInput, AlreadyAccessedError, AlreadyActiveError, AlreadyDeletedError, AlreadyInactiveError, AlreadyMemberError, AlreadyRevokedError, AlreadySettledError, type AnonymizeInput, type AppAccess, type AppCategory, type AppID, type AppId, type AppResponse, AppScopedClient, AppScopedDataClient, type AppSlug, type AppTable, type AppTemplate, AppUnavailableError, AppsClient, AuditClient, type AuditEvent, type AuditEventID, type AuthProvider, type AuthRing, AuthorizationPendingError, AuthzClient, type AuthzGrant, type AuthzSubject, type AuthzTag, AxHubClient, type AxHubClientOptions, AxHubError, type AxHubErrorInit, BadRequestError, type Branded, type BulkInviteResult, type CatalogAncestor, type CatalogConnector, type CatalogKind, type CatalogKindAction, type CatalogPermissionsReadDetail, type CatalogPermissionsReadList, type CatalogResourceDetail, type CatalogResourceFilter, type CatalogResourceView, type CatalogTag, type ColumnType, type Comment, ConfigurationError, ConflictError, type ConnectGitInput, type ConnectorID, type CreateAppInput, type CreateCategoryInput, type CreateDeploymentInput, type CreateOAuthClientInput, type CreateTableInput, type CreateTenantInput, type CursorDirection, DEFAULT_BASE_URL, type DataBulkResult, DataClient, type DataCountOptions, type DataGetOptions, type DataListOptions, type DataOrderBy, DataTableClient, type DataTableSchema, type DecideInput, type DecideResult, DecodeError, type DeploymentFailureReason, type DeploymentID, type DeploymentId, type DeploymentResponse, type DeploymentStatus, DeploymentsClient, type DeviceAuthorizationResponse, DeviceFlowDeniedError, DeviceFlowTimeoutError, type DiscoverAppsOptions, type DiscoverOptions, type DispatchContext, DomainTakenError, DuplicateError, type EmailDomain, type EmitAuditEventInput, EmptyError, type EnvVar, ExpiredTokenError, type FetchLike, type FieldError, ForbiddenError, GatewayCatalogClient, GatewayClient, type GatewayQueryColumn, type GatewayQueryInput, type GatewayQueryResult, type GitConnection, type GitConnectionSetup, type GitConnectionStatus, type GithubInstallStart, type GrantID, type GrantPrincipalType, type GrantScope, IdentityClient, IdentityDeviceCodeClient, IdentityMeClient, IdentityOAuthClient, IdentityOIDCClient, IdentityPATClient, type IdentityProvider, IdentityProviderClient, IdentitySystemOAuthClientsClient, type InferRow, type InstallStartInput, type IntegrityCheckResult, InternalServerError, IntrospectFailedError, InvalidCursorError, InvalidGrantError, InvalidPathError, InvalidStateTransitionError, InvalidValueError, InvitationExpiredError, type InviteTenantMemberInput, type InvokeInput, type InvokeResult, type IssuePersonalAccessTokenInput, type IssuePersonalAccessTokenResult, type KeysetCursor, LastAdminError, LegacyCursorError, type LikeResult, type LikeStatus, type ListAllItem, type ListAllOptions, type ListOptions, type Logger, type MeResponse, type MockClientOptions, type MockFixtures, MockInProductionError, type MockRow, type MockSchemas, MockStore, NetworkError, NoAuth, NotAdminError, NotAllowedError, NotDeletedError, NotFoundError, NotMemberError, type OAuthClient, type OAuthClientWithSecret, OAuthError, type OAuthErrorInit, type OAuthTokenResponse, type OrderByField, type PATID, type PATSummary, type PaginatedList, type ParsedFrame, type PatId, PendingExistsError, PermanentlyDeletedError, PermissionDeniedError, PoolStaleError, PreconditionFailedError, type PublicationRequest, type PublicationRequestStatus, PublicationRequestsClient, type QueryExpr, type RateLimitStrategy, RateLimitedError, type RequestId, RequiredError, type ResourceID, type RetryInfo, type SSEStream, ScanLimitExceededError, SchemaCache, type SchemaCacheOptions, SchemaNameTakenError, type SchemaShapeFromRow, type SelectColumns, type SettlePublicationInput, type SignIconUploadInput, type SignIconUploadResult, SlowDownError, SlugTakenError, StaticTokenAuth, StreamConsumedError, type StreamItem, type SubjectID, type SubmitPublicationInput, type SystemOAuthClient, type TableColumn, type TableConstraint, type TableGrant, type TableID, type TableIndex, TableNotFoundError, type TableSchema, type TagID, type Tenant, TenantGatewayClient, type TenantID, type TenantId, type TenantInvitation, type TenantMember, TenantScopedAppsClient, TenantScopedClient, type TenantSlug, TenantSlugRequiredError, TenantsClient, TimeoutError, TokenExpiredError, TokenInvalidError, TokenMissingError, type TokenType, UnauthenticatedError, UnavailableError, type UnlikeResult, type UnpublishInput, type UpdateAppInput, type UpdateGitConnectionInput, type UpdateTenantInput, type UserID, type UserId, ValidationError, type VerifyWebhookInput, type VerifyWebhookResult, WebhookVerificationError, type WebhookVerifyReason, and, asAppId, asAppSlug, asDeploymentId, asPatId, asRequestId, asTenantId, asTenantSlug, asUserId, assertMockModeAllowed, createMockStore, cursorFromRow, decodeCursor, defineSchema, dispatch, encodeCursor, escapeLike, formatErrorMessage, getAccessibleColumns, getMaskHint, id, isAllowed, isOAuthPath, isPolicyDeny, isSqlFormatError, not, or, orderByFingerprint, parseRetryAfter, raw, schemaCacheKey, signWebhook, tableFromPath, verifyWebhook, where };
3020
+ export { AbortError, AccessDeniedError, type AddColumnInput, type AddCommentInput, type AddGrantInput, AlreadyAccessedError, AlreadyActiveError, AlreadyDeletedError, AlreadyInactiveError, AlreadyMemberError, AlreadyRevokedError, AlreadySettledError, type AppAccess, type AppAvailability, type AppCategory, type AppID, type AppId, type AppInvitation, type AppMember, type AppPublicationStatus, type AppResponse, type AppResponseCategory, type AppResponseOwner, type AppReviewStatus, AppScopedClient, AppScopedDataClient, type AppSlug, type AppSort, type AppStatus, type AppTable, type AppTemplate, AppUnavailableError, type AppVisibility, AppsClient, type AuditEventID, type AuthProvider, type AuthRing, AuthorizationPendingError, AxHubClient, type AxHubClientOptions, AxHubError, type AxHubErrorInit, BadRequestError, type BootstrapAccepted, type BootstrapStage, type BootstrapStatus, type BootstrapStatusValue, type Branded, type BrowseRowsOptions, type CatalogAncestor, type CatalogConnector, type CatalogKind, type CatalogKindAction, type CatalogPermissionsReadDetail, type CatalogPermissionsReadList, type CatalogResourceDetail, type CatalogResourceFilter, type CatalogResourceView, type CatalogTag, type CheckAvailabilityInput, type ColumnType, type ColumnTypeOption, type Comment, ConfigClient, ConfigurationError, ConflictError, type ConnectGitInput, type ConnectorID, type CreateAppInput, type CreateDeploymentInput, type CreateOAuthClientInput, type CreateTableInput, type CursorBuildOptions, type CursorDirection, DEFAULT_BASE_URL, type DataBulkResult, DataClient, type DataCountOptions, type DataGetOptions, type DataListOptions, type DataOrderBy, DataTableClient, type DataTableSchema, DecodeError, type DeploymentFailureReason, type DeploymentID, type DeploymentId, type DeploymentResponse, type DeploymentStatus, DeploymentsClient, type DeviceAuthorizationResponse, DeviceFlowDeniedError, DeviceFlowTimeoutError, type DiscoverAppsOptions, type DiscoverFeedOptions, type DiscoverOptions, DomainTakenError, DuplicateError, EmptyError, type EngineCapability, type EnvVar, ExpiredTokenError, type FetchLike, type FetchLogsOptions, type FieldAvailability, type FieldError, ForbiddenError, GatewayCatalogClient, GatewayClient, type GatewayQueryColumn, type GatewayQueryInput, type GatewayQueryResult, type GitConnection, type GitConnectionSetup, type GitConnectionStatus, type GithubAccount, type GithubInstallStart, type GithubRepo, type GithubReposPage, type GrantID, type GrantPrincipalType, type GrantScope, type IconPreCreateInput, type IconPreCreateResult, IdentityClient, IdentityDeviceCodeClient, IdentityMeClient, IdentityOAuthClient, IdentityOIDCClient, IdentityPATClient, type IdentityProvider, IdentitySystemOAuthClientsClient, type InferRow, type InstallStartInput, InternalServerError, IntrospectFailedError, InvalidClientError, InvalidCursorError, InvalidGrantError, InvalidPathError, InvalidRequestError, InvalidScopeError, InvalidStateTransitionError, InvalidTargetError, InvalidTokenError, InvalidValueError, InvitationExpiredError, type InviteUserInput, type InvokeInput, type InvokeResult, type IssuePersonalAccessTokenInput, type IssuePersonalAccessTokenResult, type KeysetCursor, LastAdminError, LegacyCursorError, type LikeResult, type LikeStatus, type ListAllItem, type ListAllOptions, type ListAppsOptions, type ListMembersOptions, type ListOptions, type ListReposOptions, type LogLine, type Logger, type LogsPage, type MeResponse, type MockClientOptions, type MockFixtures, MockInProductionError, type MockRow, type MockSchemas, MockStore, NetworkError, NoAuth, NotAdminError, NotAllowedError, NotDeletedError, NotFoundError, NotMemberError, type OAuthClient, type OAuthClientWithSecret, OAuthError, type OAuthErrorInit, OAuthServerError, type OAuthTokenResponse, type OrderByField, type OrderDirection, type PATID, type PATSummary, type PageRequestOptions, type PaginatedList, type ParsedFrame, type PatId, PendingExistsError, PermanentlyDeletedError, PermissionDeniedError, PoolStaleError, PreconditionFailedError, type PublicConfig, type PublicationRequest, type PublicationRequestStatus, PublicationRequestsClient, type QueryExpr, type RateLimitStrategy, RateLimitedError, type RegisterMcpClientInput, type RegisterMcpClientResult, type RequestId, type RequestOptions, RequiredError, type ResourceID, type RetryInfo, type SSEStream, type SSEStreamOptions, ScanLimitExceededError, SchemaCache, type SchemaCacheOptions, SchemaNameTakenError, type SchemaShapeFromRow, type SelectColumns, type SettlePublicationInput, type SignIconUploadInput, type SignIconUploadResult, SlowDownError, SlugTakenError, type StartBootstrapInput, StaticTokenAuth, type StaticTokenAuthOptions, StreamConsumedError, type StreamItem, type SubjectID, type SubmitPublicationInput, type SystemOAuthClient, type TableAvailability, type TableColumn, type TableConstraint, type TableGrant, type TableID, type TableIndex, TableNotFoundError, type TableRowColumn, type TableRowsMeta, type TableRowsPage, type TableSchema, type TagID, TemporarilyUnavailableError, type Tenant, TenantGatewayClient, type TenantID, type TenantId, TenantIdRequiredError, TenantScopedAppsClient, TenantScopedClient, type TenantSlug, TenantSlugRequiredError, TenantsClient, TimeoutError, TokenExpiredError, TokenInvalidError, TokenMissingError, type TokenType, UnauthenticatedError, UnauthorizedClientError, UnavailableError, type UnlikeResult, type UnpublishInput, UnsupportedGrantTypeError, type UpdateAppInput, type UpdateGitConnectionInput, type UserID, type UserId, ValidationError, type VerifyWebhookInput, type VerifyWebhookResult, WebhookVerificationError, type WebhookVerifyReason, and, asAppId, asAppSlug, asDeploymentId, asPatId, asRequestId, asTenantId, asTenantSlug, asUserId, assertMockModeAllowed, createMockStore, cursorFromRow, decodeCursor, defineSchema, encodeCursor, escapeLike, formatErrorMessage, getAccessibleColumns, getMaskHint, id, isAllowed, isPolicyDeny, isSqlFormatError, not, or, orderByFingerprint, parseRetryAfter, raw, schemaCacheKey, signWebhook, tableFromPath, verifyWebhook, where };