@buildbase/sdk 0.0.51 → 0.0.54

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.
Files changed (50) hide show
  1. package/AGENTS.md +24 -8
  2. package/CHANGELOG.md +102 -0
  3. package/README.md +283 -33
  4. package/dist/css/styles.css +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.d.ts +1248 -76
  7. package/dist/index.mjs +1 -1
  8. package/dist/mcp/index.cjs +1 -0
  9. package/dist/mcp/index.d.ts +1956 -0
  10. package/dist/mcp/index.mjs +1 -0
  11. package/dist/react/chunks/{SettingsDialog-DitAiAqr.cjs → SettingsDialog-B28WJsAr.cjs} +1 -1
  12. package/dist/react/chunks/{SettingsDialog-uVKFxlal.mjs → SettingsDialog-blhppbNm.mjs} +1 -1
  13. package/dist/react/chunks/{SubscriptionDialog-P0GlXEyn.mjs → SubscriptionDialog-BTWVX3cH.mjs} +1 -1
  14. package/dist/react/chunks/{SubscriptionDialog-Cg-qYVKr.cjs → SubscriptionDialog-QKmwvJU1.cjs} +1 -1
  15. package/dist/react/chunks/ar-1Z1MOGAP.mjs +2 -0
  16. package/dist/react/chunks/ar-VGzBv3AZ.cjs +2 -0
  17. package/dist/react/chunks/de-BjdDg60Y.cjs +2 -0
  18. package/dist/react/chunks/de-CXUItplO.mjs +2 -0
  19. package/dist/react/chunks/es-BBPsSZUp.cjs +2 -0
  20. package/dist/react/chunks/es-BTbzVutz.mjs +2 -0
  21. package/dist/react/chunks/fr-Cax48X_S.cjs +2 -0
  22. package/dist/react/chunks/fr-DPMeOQu3.mjs +2 -0
  23. package/dist/react/chunks/hi-BJqvpG6d.cjs +2 -0
  24. package/dist/react/chunks/hi-JfJx-LV7.mjs +2 -0
  25. package/dist/react/chunks/ja-CDGtLzTk.mjs +2 -0
  26. package/dist/react/chunks/ja-DvVyj5xX.cjs +2 -0
  27. package/dist/react/chunks/react-6QJCOE-D.cjs +2 -0
  28. package/dist/react/chunks/react-CC6T7Zky.mjs +2 -0
  29. package/dist/react/chunks/zh-BAcqxkxk.cjs +2 -0
  30. package/dist/react/chunks/zh-BNZ2Ooe8.mjs +2 -0
  31. package/dist/react/index.cjs +1 -1
  32. package/dist/react/index.d.ts +98 -43
  33. package/dist/react/index.mjs +1 -1
  34. package/package.json +20 -5
  35. package/dist/react/chunks/ar-SrPOJXdL.mjs +0 -2
  36. package/dist/react/chunks/ar-a3aRbPCs.cjs +0 -2
  37. package/dist/react/chunks/de-DE3_z7r0.cjs +0 -2
  38. package/dist/react/chunks/de-xnPl61SS.mjs +0 -2
  39. package/dist/react/chunks/es-C_xcyGtp.cjs +0 -2
  40. package/dist/react/chunks/es-CyuBtosP.mjs +0 -2
  41. package/dist/react/chunks/fr-BMu7Bk4k.cjs +0 -2
  42. package/dist/react/chunks/fr-CxuDLZ27.mjs +0 -2
  43. package/dist/react/chunks/hi-CQ215yc9.cjs +0 -2
  44. package/dist/react/chunks/hi-CpuvyorS.mjs +0 -2
  45. package/dist/react/chunks/ja-DIJ_xCIi.mjs +0 -2
  46. package/dist/react/chunks/ja-DK6Buuws.cjs +0 -2
  47. package/dist/react/chunks/react-C2ikFWBG.cjs +0 -2
  48. package/dist/react/chunks/react-CCukNQ4q.mjs +0 -2
  49. package/dist/react/chunks/zh-CYQwZiBL.mjs +0 -2
  50. package/dist/react/chunks/zh-Dt-apS2s.cjs +0 -2
package/dist/index.d.ts CHANGED
@@ -1116,6 +1116,8 @@ declare abstract class BaseApi {
1116
1116
  private reportError;
1117
1117
  /** Execute fetch with timeout, retries, debug logging, and error callback. */
1118
1118
  private executeFetch;
1119
+ /** Backoff sleep that ends early (with an AbortError) when the signal fires. */
1120
+ private static delay;
1119
1121
  /** Internal: execute fetch against a resolved URL with timeout, retries, debug logging, and error callback. */
1120
1122
  private executeFetchUrl;
1121
1123
  /**
@@ -1860,15 +1862,40 @@ declare function cleanBBParams(): void;
1860
1862
  /**
1861
1863
  * Security utilities for the SDK.
1862
1864
  */
1865
+ /** Options for {@link validateRedirectUrl}. */
1866
+ interface RedirectValidationOptions {
1867
+ /**
1868
+ * Require absolute URLs to be same-origin with the current page
1869
+ * (`window.location.origin`). Relative paths always pass. Use for any
1870
+ * user-controllable target (return URLs, `?next=` params) — it turns an
1871
+ * open redirect into a same-site navigation. Outside a browser there is no
1872
+ * origin to compare against, so absolute URLs are rejected.
1873
+ */
1874
+ sameOrigin?: boolean;
1875
+ /**
1876
+ * Origins additionally allowed for absolute URLs, e.g.
1877
+ * `['https://checkout.stripe.com']`. Matched against `URL.origin` exactly.
1878
+ */
1879
+ allowedOrigins?: string[];
1880
+ }
1863
1881
  /**
1864
- * Validate that a URL is safe to redirect to.
1865
- * Prevents open redirect attacks by ensuring the URL uses https (or http on localhost).
1866
- * Returns the URL if safe, or null if not.
1882
+ * Validate that a URL is safe to redirect to. Returns the URL if safe, null if
1883
+ * not.
1884
+ *
1885
+ * - **Relative paths** (`/dashboard`) are safe and always allowed —
1886
+ * protocol-relative (`//evil.com`) and backslash (`/\evil.com`) forms are
1887
+ * not treated as relative.
1888
+ * - **Absolute URLs** must be `https:` (or `http:` on localhost). By default
1889
+ * any such URL passes (needed for cross-origin targets like Stripe checkout);
1890
+ * pass `sameOrigin` and/or `allowedOrigins` to restrict — then the URL must
1891
+ * match at least one of them. Always restrict user-controllable targets.
1867
1892
  */
1868
- declare function validateRedirectUrl(url: string | null | undefined): string | null;
1893
+ declare function validateRedirectUrl(url: string | null | undefined, options?: RedirectValidationOptions): string | null;
1869
1894
  /**
1870
1895
  * Safely redirect to a URL after validating it.
1871
- * Falls back to fallbackUrl if the target URL is invalid.
1896
+ * Falls back to fallbackUrl (itself validated — else `/`) if the target URL is
1897
+ * invalid. Pass `options` to restrict user-controllable targets (see
1898
+ * {@link validateRedirectUrl}).
1872
1899
  *
1873
1900
  * Browser-only: navigation requires `window.location`. On non-browser runtimes
1874
1901
  * (Node, edge, Deno, Bun) there is nothing to navigate, so this is a no-op that
@@ -1876,7 +1903,7 @@ declare function validateRedirectUrl(url: string | null | undefined): string | n
1876
1903
  * that needs the resolved target should call {@link validateRedirectUrl} and
1877
1904
  * issue the redirect with its own framework (e.g. `Response.redirect`).
1878
1905
  */
1879
- declare function safeRedirect(url: string | null | undefined, fallbackUrl?: string): boolean;
1906
+ declare function safeRedirect(url: string | null | undefined, fallbackUrl?: string, options?: RedirectValidationOptions): boolean;
1880
1907
 
1881
1908
  /**
1882
1909
  * Auth intent preservation — saves and restores the URL the user was on
@@ -1884,7 +1911,8 @@ declare function safeRedirect(url: string | null | undefined, fallbackUrl?: stri
1884
1911
  */
1885
1912
  /**
1886
1913
  * Save the current URL as the post-auth redirect target.
1887
- * Validates the URL before storing — rejects unsafe URLs silently.
1914
+ * Validates the URL before storing — rejects unsafe URLs silently. Same-origin
1915
+ * only: the return URL is "where the user was", never another site.
1888
1916
  */
1889
1917
  declare function saveAuthIntent(returnUrl: string): void;
1890
1918
  /**
@@ -1916,7 +1944,15 @@ declare const PLAN_CURRENCY_OPTIONS: {
1916
1944
  value: "usd" | "eur" | "gbp" | "jpy" | "cad" | "aud" | "chf" | "cny" | "hkd" | "sgd" | "inr" | "mxn" | "brl" | "nzd" | "sek" | "nok" | "dkk" | "pln" | "thb";
1917
1945
  label: string;
1918
1946
  }[];
1919
- /** Format cents as money string (e.g. 1999, "usd" -> "$19.99"). Caller must pass currency (e.g. from plan or workspace). */
1947
+ /** True when `currency` has no minor unit (JPY, KRW, …) — amounts are whole units, not cents. */
1948
+ declare function isZeroDecimalCurrency(currency: string | null | undefined): boolean;
1949
+ /**
1950
+ * Convert a minor-unit amount to its display number for `currency`:
1951
+ * `minorAmountToDisplay(1999, 'usd')` → `"19.99"`,
1952
+ * `minorAmountToDisplay(1000, 'jpy')` → `"1,000"` (zero-decimal — no division).
1953
+ */
1954
+ declare function minorAmountToDisplay(amount: number, currency: string): string;
1955
+ /** Format cents as money string (e.g. 1999, "usd" -> "$19.99"; 1000, "jpy" -> "¥1,000"). Caller must pass currency (e.g. from plan or workspace). */
1920
1956
  declare function formatCents(cents: number, currency: string): string;
1921
1957
  /** Translatable labels for overage/quota formatting */
1922
1958
  interface OverageLabels {
@@ -2186,8 +2222,9 @@ interface PermissionContext {
2186
2222
  * 3. settings.workspace.permissions[role] (org-level template)
2187
2223
  * 4. DEFAULT_ROLE_PERMISSIONS[role] (SDK built-in defaults)
2188
2224
  * 5. Merge in appPermissions (developer-defined) for the role
2189
- * 6. If role not found → use defaultRole from settings, then 'member'
2190
- * 7. Apply setting restrictions (canInviteMembers, canCreateWorkspace)
2225
+ * 6. If role not found → use an explicitly-configured, known `defaultRole`;
2226
+ * otherwise deny (no silent 'member' fallback for unknown roles)
2227
+ * 7. Apply setting restrictions (canInviteMembers)
2191
2228
  */
2192
2229
  declare function resolvePermissions(ctx: PermissionContext): Set<string>;
2193
2230
  /**
@@ -2222,6 +2259,652 @@ interface BetaFormResponse {
2222
2259
  message: string;
2223
2260
  }
2224
2261
 
2262
+ /**
2263
+ * Type-safe translation keys for the BuildBase SDK.
2264
+ * All user-facing strings are defined here.
2265
+ */
2266
+ interface SDKMessages {
2267
+ security: {
2268
+ connectedAgentsTitle: string;
2269
+ connectedAgentsDescription: string;
2270
+ connectedAgentsDisconnect: string;
2271
+ connectedAgentsEmpty: string;
2272
+ connectedAgentsAccess: string;
2273
+ connectedAgentsGranted: string;
2274
+ inactive: string;
2275
+ inactiveHint: string;
2276
+ passkeysTitle: string;
2277
+ passkeysDescription: string;
2278
+ noPasskeys: string;
2279
+ addHint: string;
2280
+ rename: string;
2281
+ remove: string;
2282
+ removeTitle: string;
2283
+ removeDescription: string;
2284
+ renamePlaceholder: string;
2285
+ lastUsed: string;
2286
+ added: string;
2287
+ };
2288
+ settings: {
2289
+ titles: {
2290
+ profile: string;
2291
+ security: string;
2292
+ general: string;
2293
+ users: string;
2294
+ subscription: string;
2295
+ usage: string;
2296
+ credits: string;
2297
+ features: string;
2298
+ notifications: string;
2299
+ permissions: string;
2300
+ danger: string;
2301
+ };
2302
+ sidebar: {
2303
+ account: string;
2304
+ workspace: string;
2305
+ profile: string;
2306
+ security: string;
2307
+ general: string;
2308
+ users: string;
2309
+ subscription: string;
2310
+ usage: string;
2311
+ credits: string;
2312
+ features: string;
2313
+ notifications: string;
2314
+ permissions: string;
2315
+ danger: string;
2316
+ };
2317
+ common: {
2318
+ refresh: string;
2319
+ refreshing: string;
2320
+ retry: string;
2321
+ retrying: string;
2322
+ save: string;
2323
+ saving: string;
2324
+ cancel: string;
2325
+ delete: string;
2326
+ dismiss: string;
2327
+ loading: string;
2328
+ success: string;
2329
+ error: string;
2330
+ refreshAction: string;
2331
+ retryAction: string;
2332
+ noPermissionTitle: string;
2333
+ noPermissionDescription: string;
2334
+ billingManageOnly: string;
2335
+ openSettings: string;
2336
+ back: string;
2337
+ };
2338
+ };
2339
+ subscription: {
2340
+ managePlan: string;
2341
+ changePlan: string;
2342
+ viewPricingPlans: string;
2343
+ viewPlans: string;
2344
+ upgradePlan: string;
2345
+ subscribe: string;
2346
+ currentPlan: string;
2347
+ noSubscription: string;
2348
+ choosePlan: string;
2349
+ choosePlanDescription: string;
2350
+ forWorkspace: string;
2351
+ planUpdateAvailable: string;
2352
+ updateSuccess: string;
2353
+ updateFailed: string;
2354
+ cancelTitle: string;
2355
+ cancelConfirm: string;
2356
+ cancelKeep: string;
2357
+ cancelButton: string;
2358
+ canceling: string;
2359
+ cancelSuccess: string;
2360
+ cancelNotCharged: string;
2361
+ cancelResumeAnytime: string;
2362
+ cancelTrialTitle: string;
2363
+ cancelTrialConfirm: string;
2364
+ cancelTrialAccess: string;
2365
+ cancelTrialNoCharge: string;
2366
+ cancelTrialResume: string;
2367
+ cancelTrialKeep: string;
2368
+ cancelTrialButton: string;
2369
+ resumeTitle: string;
2370
+ resumeTrial: string;
2371
+ resumeConfirm: string;
2372
+ resumeKeep: string;
2373
+ resumeButton: string;
2374
+ resuming: string;
2375
+ resumeSuccess: string;
2376
+ managePayment: string;
2377
+ openingPortal: string;
2378
+ viewAllPlans: string;
2379
+ scheduledCancellation: string;
2380
+ scheduledTrialCancellation: string;
2381
+ paymentPastDue: string;
2382
+ paymentPastDueDescription: string;
2383
+ subscriptionPaused: string;
2384
+ subscriptionPausedDescription: string;
2385
+ errorLoading: string;
2386
+ errorLoadingDescription: string;
2387
+ errorProcessing: string;
2388
+ errorCanceling: string;
2389
+ errorResuming: string;
2390
+ invalidWorkspace: string;
2391
+ billingInterval: {
2392
+ monthly: string;
2393
+ quarterly: string;
2394
+ yearly: string;
2395
+ perMonth: string;
2396
+ perQuarter: string;
2397
+ perYear: string;
2398
+ };
2399
+ seats: {
2400
+ title: string;
2401
+ members: string;
2402
+ included: string;
2403
+ billable: string;
2404
+ perExtraSeat: string;
2405
+ limit: string;
2406
+ includedSeats: string;
2407
+ maxSeats: string;
2408
+ freeWithBase: string;
2409
+ allIncluded: string;
2410
+ extra: string;
2411
+ unlimited: string;
2412
+ };
2413
+ items: {
2414
+ features: string;
2415
+ limits: string;
2416
+ quotas: string;
2417
+ credits: string;
2418
+ creditsPerMonth: string;
2419
+ creditsOneTime: string;
2420
+ creditRenewal: string;
2421
+ creditModeReset: string;
2422
+ creditModeTopup: string;
2423
+ creditModeLifetime: string;
2424
+ /** @deprecated */
2425
+ creditsPerPeriod: string;
2426
+ /** @deprecated */
2427
+ creditRollover: string;
2428
+ };
2429
+ checkout: {
2430
+ upgrade: string;
2431
+ downgrade: string;
2432
+ switchTo: string;
2433
+ select: string;
2434
+ };
2435
+ status: {
2436
+ active: string;
2437
+ canceling: string;
2438
+ trial: string;
2439
+ canceled: string;
2440
+ pastDue: string;
2441
+ paused: string;
2442
+ deprecated: string;
2443
+ unknown: string;
2444
+ };
2445
+ plan: string;
2446
+ invoicesTab: string;
2447
+ tabsLabel: string;
2448
+ endsOn: string;
2449
+ versionLabel: string;
2450
+ changePlanButton: string;
2451
+ noPlanAssigned: string;
2452
+ free: string;
2453
+ perSeatDisplay: string;
2454
+ estTotalDisplay: string;
2455
+ nextBillingDisplay: string;
2456
+ membersInWorkspace: string;
2457
+ billingInCurrency: string;
2458
+ savingsPercent: string;
2459
+ switchToInterval: string;
2460
+ seatPriceDisplay: string;
2461
+ trialEnded: string;
2462
+ trialEndsIn: string;
2463
+ onTrial: string;
2464
+ upgradeToKeepAccess: string;
2465
+ viewInvoices: string;
2466
+ cancelTrial: string;
2467
+ dunningFinal: string;
2468
+ dunningSuspended: string;
2469
+ dunningRecovery: string;
2470
+ dunningSuspendedDescription: string;
2471
+ dunningRecoveryDescription: string;
2472
+ cancelEndDescription: string;
2473
+ trialEndDescription: string;
2474
+ cancelEndFallback: string;
2475
+ resumeChargeDate: string;
2476
+ resumeChargeFallback: string;
2477
+ resumeContinue: string;
2478
+ resumeCancelAnytime: string;
2479
+ retainAccess: string;
2480
+ retainAccessFallback: string;
2481
+ noPlansAvailable: string;
2482
+ noPlansAvailableHint: string;
2483
+ startTrialDescription: string;
2484
+ noSubscriptionDescription: string;
2485
+ startFreeTrial: string;
2486
+ startTrialDays: string;
2487
+ trialBadge: string;
2488
+ };
2489
+ users: {
2490
+ emailPlaceholder: string;
2491
+ title: string;
2492
+ adminOnly: string;
2493
+ inviteByEmail: string;
2494
+ inviteButton: string;
2495
+ inviting: string;
2496
+ inviteSuccess: string;
2497
+ emailRequired: string;
2498
+ invalidEmail: string;
2499
+ inviteFailed: string;
2500
+ seatLimitReached: string;
2501
+ memberLimitReached: string;
2502
+ role: string;
2503
+ you: string;
2504
+ owner: string;
2505
+ noMembers: string;
2506
+ extraSeatCost: string;
2507
+ unknownUser: string;
2508
+ seats: string;
2509
+ members: string;
2510
+ included: string;
2511
+ perExtraSeat: string;
2512
+ maxMembers: string;
2513
+ available: string;
2514
+ noMemberLimit: string;
2515
+ seatHeading: string;
2516
+ limitReached: string;
2517
+ memberCount: string;
2518
+ subscriptionRequired: string;
2519
+ seatLimitMessage: string;
2520
+ settingsLimitMessage: string;
2521
+ memberLimitMessage: string;
2522
+ selectRole: string;
2523
+ inviteAs: string;
2524
+ };
2525
+ invoices: {
2526
+ title: string;
2527
+ description: string;
2528
+ pay: string;
2529
+ view: string;
2530
+ viewDetails: string;
2531
+ download: string;
2532
+ errorLoading: string;
2533
+ noInvoices: string;
2534
+ noInvoicesWithSub: string;
2535
+ paidAmount: string;
2536
+ na: string;
2537
+ status: {
2538
+ draft: string;
2539
+ open: string;
2540
+ paid: string;
2541
+ uncollectible: string;
2542
+ void: string;
2543
+ };
2544
+ };
2545
+ usage: {
2546
+ title: string;
2547
+ description: string;
2548
+ totalResources: string;
2549
+ overallUsage: string;
2550
+ inOverage: string;
2551
+ estOverageCost: string;
2552
+ overageDetected: string;
2553
+ overageDescription: string;
2554
+ overageUnits: string;
2555
+ rate: string;
2556
+ billableBlocks: string;
2557
+ estimatedCharge: string;
2558
+ noData: string;
2559
+ noDataHint: string;
2560
+ used: string;
2561
+ remaining: string;
2562
+ overLimit: string;
2563
+ percentUsed: string;
2564
+ availableRemaining: string;
2565
+ overLimitCount: string;
2566
+ overageWarning: string;
2567
+ fullyUsed: string;
2568
+ renewingSoon: string;
2569
+ almostFull: string;
2570
+ overage: string;
2571
+ errorLoading: string;
2572
+ perUnit: string;
2573
+ perUnits: string;
2574
+ rateDisplay: string;
2575
+ resourcesExceeded: string;
2576
+ estOverageCharges: string;
2577
+ overageRateDisplay: string;
2578
+ resetDateDisplay: string;
2579
+ daysRemainingDisplay: string;
2580
+ };
2581
+ profile: {
2582
+ email: string;
2583
+ name: string;
2584
+ language: string;
2585
+ country: string;
2586
+ currency: string;
2587
+ timezone: string;
2588
+ profileImage: string;
2589
+ success: string;
2590
+ nameMinLength: string;
2591
+ save: string;
2592
+ reset: string;
2593
+ };
2594
+ general: {
2595
+ ownerOnly: string;
2596
+ name: string;
2597
+ namePlaceholder: string;
2598
+ nameMinLength: string;
2599
+ billingCurrency: string;
2600
+ icon: string;
2601
+ iconDescription: string;
2602
+ imageUrl: string;
2603
+ imageUrlPlaceholder: string;
2604
+ imageUrlDescription: string;
2605
+ previewLabel: string;
2606
+ previewImageAlt: string;
2607
+ success: string;
2608
+ chooseEmoji: string;
2609
+ customImageUrl: string;
2610
+ updateWorkspace: string;
2611
+ };
2612
+ features: {
2613
+ title: string;
2614
+ ownerOnly: string;
2615
+ noFeatures: string;
2616
+ enabled: string;
2617
+ disabled: string;
2618
+ enabling: string;
2619
+ disabling: string;
2620
+ featureSuccess: string;
2621
+ updateSuccess: string;
2622
+ actionStatus: string;
2623
+ };
2624
+ danger: {
2625
+ title: string;
2626
+ adminOnly: string;
2627
+ deleteWorkspace: string;
2628
+ deleteConfirm: string;
2629
+ deleteWarning: string;
2630
+ deleting: string;
2631
+ deleteDescription: string;
2632
+ deleteConfirmDescription: string;
2633
+ failedToDelete: string;
2634
+ };
2635
+ notifications: {
2636
+ title: string;
2637
+ permissionDenied: string;
2638
+ notSupported: string;
2639
+ manageDescription: string;
2640
+ blocked: string;
2641
+ blockedDescription: string;
2642
+ pushTitle: string;
2643
+ pushEnabledDescription: string;
2644
+ pushDisabledDescription: string;
2645
+ enabling: string;
2646
+ disabling: string;
2647
+ enable: string;
2648
+ disable: string;
2649
+ toggleAction: string;
2650
+ pushDescription: string;
2651
+ deviceNote: string;
2652
+ prefsSaved: string;
2653
+ loadingPrefs: string;
2654
+ categories: {
2655
+ workspace: string;
2656
+ billing: string;
2657
+ };
2658
+ events: {
2659
+ workspace_invite: string;
2660
+ workspace_invite_desc: string;
2661
+ workspace_removed: string;
2662
+ workspace_removed_desc: string;
2663
+ workspace_role_changed: string;
2664
+ workspace_role_changed_desc: string;
2665
+ subscription_created: string;
2666
+ subscription_created_desc: string;
2667
+ subscription_upgraded: string;
2668
+ subscription_upgraded_desc: string;
2669
+ subscription_canceled: string;
2670
+ subscription_canceled_desc: string;
2671
+ subscription_suspended: string;
2672
+ subscription_suspended_desc: string;
2673
+ trial_ending: string;
2674
+ trial_ending_desc: string;
2675
+ trial_expired: string;
2676
+ trial_expired_desc: string;
2677
+ payment_failed: string;
2678
+ payment_failed_desc: string;
2679
+ payment_action_required: string;
2680
+ payment_action_required_desc: string;
2681
+ payment_succeeded: string;
2682
+ payment_succeeded_desc: string;
2683
+ };
2684
+ unblock: {
2685
+ firefox: {
2686
+ step1: string;
2687
+ step2: string;
2688
+ step3: string;
2689
+ step4: string;
2690
+ };
2691
+ safari: {
2692
+ step1: string;
2693
+ step2: string;
2694
+ step3: string;
2695
+ step4: string;
2696
+ };
2697
+ edge: {
2698
+ step1: string;
2699
+ step2: string;
2700
+ step3: string;
2701
+ step4: string;
2702
+ };
2703
+ chrome: {
2704
+ step1: string;
2705
+ step2: string;
2706
+ step3: string;
2707
+ step4: string;
2708
+ };
2709
+ };
2710
+ };
2711
+ quota: {
2712
+ includedOnly: string;
2713
+ includedWithOverage: string;
2714
+ includedHardLimit: string;
2715
+ unitFallback: string;
2716
+ };
2717
+ pricing: {
2718
+ title: string;
2719
+ description: string;
2720
+ currency: string;
2721
+ billingIn: string;
2722
+ noPlansCurrency: string;
2723
+ noPlansCurrencyHint: string;
2724
+ noPlans: string;
2725
+ free: string;
2726
+ included: string;
2727
+ save: string;
2728
+ current: string;
2729
+ processing: string;
2730
+ unavailable: string;
2731
+ selectCurrency: string;
2732
+ billingInterval: string;
2733
+ };
2734
+ beta: {
2735
+ logoAlt: string;
2736
+ nameLabel: string;
2737
+ emailLabel: string;
2738
+ submitText: string;
2739
+ submittingText: string;
2740
+ errorMessage: string;
2741
+ tryAgain: string;
2742
+ privacyConsent: string;
2743
+ privacyPolicy: string;
2744
+ and: string;
2745
+ termsOfService: string;
2746
+ };
2747
+ workspace: {
2748
+ switchTitle: string;
2749
+ switchDescription: string;
2750
+ notLoggedIn: string;
2751
+ availableWorkspaces: string;
2752
+ loadingWorkspaces: string;
2753
+ searchPlaceholder: string;
2754
+ noWorkspacesFound: string;
2755
+ noWorkspacesAvailable: string;
2756
+ switchTo: string;
2757
+ membersCount: string;
2758
+ createNew: string;
2759
+ createTitle: string;
2760
+ createDescription: string;
2761
+ workspaceName: string;
2762
+ workspaceNamePlaceholder: string;
2763
+ workspaceNameMinLength: string;
2764
+ workspaceIcon: string;
2765
+ iconDescription: string;
2766
+ chooseEmoji: string;
2767
+ customImageUrl: string;
2768
+ imageUrl: string;
2769
+ imageUrlPlaceholder: string;
2770
+ imageUrlDescription: string;
2771
+ invalidUrl: string;
2772
+ creating: string;
2773
+ createWorkspace: string;
2774
+ };
2775
+ dropdowns: {
2776
+ search: string;
2777
+ chooseOption: string;
2778
+ chooseCountry: string;
2779
+ searchCountry: string;
2780
+ chooseLanguage: string;
2781
+ searchLanguage: string;
2782
+ chooseCurrency: string;
2783
+ searchCurrency: string;
2784
+ chooseTimezone: string;
2785
+ searchTimezone: string;
2786
+ noResults: string;
2787
+ };
2788
+ push: {
2789
+ failedToSubscribe: string;
2790
+ failedToUnsubscribe: string;
2791
+ };
2792
+ permissions: {
2793
+ title: string;
2794
+ description: string;
2795
+ ownerOnly: string;
2796
+ save: string;
2797
+ saving: string;
2798
+ saveSuccess: string;
2799
+ };
2800
+ credits: {
2801
+ title: string;
2802
+ description: string;
2803
+ balance: string;
2804
+ available: string;
2805
+ totalGranted: string;
2806
+ totalConsumed: string;
2807
+ totalExpired: string;
2808
+ noCredits: string;
2809
+ noCreditsHint: string;
2810
+ buyCredits: string;
2811
+ buyAmount: string;
2812
+ purchasing: string;
2813
+ packages: string;
2814
+ noPackages: string;
2815
+ creditsAmount: string;
2816
+ validityDays: string;
2817
+ validityUnlimited: string;
2818
+ transactions: string;
2819
+ noTransactions: string;
2820
+ loadMore: string;
2821
+ viewAll: string;
2822
+ expiringSoon: string;
2823
+ expiringInDays: string;
2824
+ noExpiring: string;
2825
+ type: {
2826
+ plan_grant: string;
2827
+ pack_purchased: string;
2828
+ consumed: string;
2829
+ expired: string;
2830
+ admin_grant: string;
2831
+ admin_revoke: string;
2832
+ refund: string;
2833
+ };
2834
+ dialogTitle: string;
2835
+ dialogDescription: string;
2836
+ dialogDescriptionWorkspace: string;
2837
+ perCredit: string;
2838
+ purchaseSuccess: string;
2839
+ purchaseCanceled: string;
2840
+ purchaseFailed: string;
2841
+ errorLoading: string;
2842
+ insufficientCredits: string;
2843
+ };
2844
+ loading: {
2845
+ restoringSession: string;
2846
+ redirecting: string;
2847
+ signingIn: string;
2848
+ verifyingAccount: string;
2849
+ almostThere: string;
2850
+ };
2851
+ errors: {
2852
+ networkError: string;
2853
+ unauthorized: string;
2854
+ notFound: string;
2855
+ generic: string;
2856
+ fetchPlans: string;
2857
+ fetchPlanGroup: string;
2858
+ fetchPlanGroupVersion: string;
2859
+ fetchPlanGroupVersions: string;
2860
+ fetchSubscription: string;
2861
+ createCheckout: string;
2862
+ updateSubscription: string;
2863
+ fetchInvoices: string;
2864
+ fetchInvoice: string;
2865
+ openBillingPortal: string;
2866
+ cancelSubscription: string;
2867
+ resumeSubscription: string;
2868
+ recordUsage: string;
2869
+ fetchQuotaUsage: string;
2870
+ fetchAllQuotaUsage: string;
2871
+ fetchUsageLogs: string;
2872
+ fetchCreditBalance: string;
2873
+ consumeCredits: string;
2874
+ purchaseCredits: string;
2875
+ fetchCreditPackages: string;
2876
+ fetchCreditTransactions: string;
2877
+ fetchExpiringCredits: string;
2878
+ };
2879
+ }
2880
+ /**
2881
+ * Generates a union of all valid dot-separated key paths from SDKMessages.
2882
+ * Supports up to 4 levels of nesting (covers all current keys, e.g.
2883
+ * "notifications.unblock.firefox.step1").
2884
+ * Used to make `t()` calls compile-time safe with autocomplete.
2885
+ *
2886
+ * @example
2887
+ * TranslationKey → "settings.titles.profile" | "settings.common.refresh" | ...
2888
+ */
2889
+ type Level1 = keyof SDKMessages & string;
2890
+ type Level2 = {
2891
+ [K1 in Level1]: SDKMessages[K1] extends Record<string, unknown> ? `${K1}.${keyof SDKMessages[K1] & string}` : never;
2892
+ }[Level1];
2893
+ type Level3 = {
2894
+ [K1 in Level1]: SDKMessages[K1] extends Record<string, unknown> ? {
2895
+ [K2 in keyof SDKMessages[K1] & string]: SDKMessages[K1][K2] extends Record<string, unknown> ? `${K1}.${K2}.${keyof SDKMessages[K1][K2] & string}` : never;
2896
+ }[keyof SDKMessages[K1] & string] : never;
2897
+ }[Level1];
2898
+ type Level4 = {
2899
+ [K1 in Level1]: SDKMessages[K1] extends Record<string, unknown> ? {
2900
+ [K2 in keyof SDKMessages[K1] & string]: SDKMessages[K1][K2] extends Record<string, unknown> ? {
2901
+ [K3 in keyof SDKMessages[K1][K2] & string]: SDKMessages[K1][K2][K3] extends Record<string, unknown> ? `${K1}.${K2}.${K3}.${keyof SDKMessages[K1][K2][K3] & string}` : never;
2902
+ }[keyof SDKMessages[K1][K2] & string] : never;
2903
+ }[keyof SDKMessages[K1] & string] : never;
2904
+ }[Level1];
2905
+ /** Union of all valid translation key paths (e.g. "settings.titles.profile") */
2906
+ type TranslationKey = Level2 | Level3 | Level4;
2907
+
2225
2908
  /**
2226
2909
  * Verify that a webhook request came from BuildBase.
2227
2910
  *
@@ -2310,17 +2993,17 @@ declare function parseWebhookEvent(options: {
2310
2993
  *
2311
2994
  * Makes a consuming app "agent ready" (see https://isitagentready.com) by
2312
2995
  * serving the standard machine-readable discovery documents an AI agent looks
2313
- * for — with the BuildBase server as the source of truth.
2314
- *
2315
- * The heavy lifting already lives on the platform: an org admin configures
2316
- * agent readiness once (protected resources, scopes, llms.txt) and the server
2317
- * publishes the OAuth2 authorization-server metadata (RFC 8414) and the
2318
- * per-resource protected-resource metadata (RFC 9728). This module lets an app
2319
- * re-serve those documents from its own origin — where agents actually look —
2320
- * plus generate the static discovery documents (Agent Card, Agent Skills,
2321
- * security.txt) from local config. The result: an org admin adds full agent
2322
- * support to their app in a couple of lines, and never hand-writes a
2323
- * `.well-known` route.
2996
+ * for.
2997
+ *
2998
+ * Ownership is split: the platform owns AUTH — it publishes the OAuth2
2999
+ * authorization-server metadata (RFC 8414) and this module re-serves it from
3000
+ * the app's origin, where agents actually look. Everything else (protected
3001
+ * resources and their scopes, RFC 9728 metadata, llms.txt, sitemap, Agent
3002
+ * Card, Agent Skills, security.txt) is CONTENT the app owns — declared locally
3003
+ * in {@link AgentReadyConfig} and generated here; the shared authorization
3004
+ * server stays scope- and resource-agnostic. The result: an org admin adds
3005
+ * full agent support to their app in a couple of lines, and never hand-writes
3006
+ * a `.well-known` route.
2324
3007
  *
2325
3008
  * Zero React and no framework types — every function returns plain data. The
2326
3009
  * only runtime dependency is `fetch`; SHA-256 (for Agent Skills digests) is a
@@ -2332,34 +3015,31 @@ declare function parseWebhookEvent(options: {
2332
3015
  * @example Next.js App Router — the entire integration:
2333
3016
  * ```ts
2334
3017
  * // lib/agent-ready.ts
2335
- * import type { AgentReadyConfig } from "@buildbase/sdk";
3018
+ * import { resolveAgentPath, type AgentReadyConfig } from "@buildbase/sdk";
2336
3019
  * export const agentConfig: AgentReadyConfig = {
2337
3020
  * serverUrl: process.env.BUILDBASE_URL!,
2338
3021
  * orgId: process.env.BUILDBASE_ORG_ID!,
2339
3022
  * siteUrl: "https://imejis.io",
2340
3023
  * site: { name: "Imejis", description: "Generate images from templates via API." },
3024
+ * robots: { contentSignals: { search: true, aiInput: true, aiTrain: false } },
2341
3025
  * };
2342
- *
2343
- * // app/.well-known/[...path]/route.ts
2344
- * import { resolveWellKnown } from "@buildbase/sdk";
2345
- * import { agentConfig } from "@/lib/agent-ready";
2346
- * export async function GET(req: Request) {
2347
- * const doc = await resolveWellKnown(new URL(req.url).pathname, agentConfig);
3026
+ * export async function serveAgentPath(req: Request): Promise<Response> {
3027
+ * const doc = await resolveAgentPath(new URL(req.url).pathname, agentConfig);
2348
3028
  * if (!doc) return new Response('{"error":"not_found"}', { status: 404 });
2349
3029
  * return new Response(doc.body, {
2350
3030
  * status: doc.status,
2351
- * headers: { "Content-Type": doc.contentType, "Cache-Control": doc.cacheControl },
3031
+ * headers: {
3032
+ * "Content-Type": doc.contentType,
3033
+ * "Cache-Control": doc.cacheControl,
3034
+ * ...(doc.vary ? { Vary: doc.vary } : {}),
3035
+ * },
2352
3036
  * });
2353
3037
  * }
2354
3038
  *
2355
- * // app/llms.txt/route.ts
2356
- * import { buildLlmsTxt, fetchAgentReadiness } from "@buildbase/sdk";
2357
- * import { agentConfig } from "@/lib/agent-ready";
2358
- * export async function GET() {
2359
- * const doc = buildLlmsTxt(agentConfig, await fetchAgentReadiness(agentConfig));
2360
- * if (!doc) return new Response("Not found", { status: 404 });
2361
- * return new Response(doc.body, { headers: { "Content-Type": doc.contentType } });
2362
- * }
3039
+ * // app/.well-known/[...path]/route.ts — plus identical two-liners at
3040
+ * // app/robots.txt/route.ts, app/llms.txt/route.ts, app/auth.md/route.ts, …
3041
+ * import { serveAgentPath } from "@/lib/agent-ready";
3042
+ * export const GET = serveAgentPath;
2363
3043
  * ```
2364
3044
  */
2365
3045
  /**
@@ -2370,21 +3050,16 @@ declare function parseWebhookEvent(options: {
2370
3050
  interface AgentReadinessBundle {
2371
3051
  /** False when the org has not enabled agent readiness — everything else absent. */
2372
3052
  enabled: boolean;
2373
- /** Pointer to the org's RFC 8414 authorization-server metadata. */
3053
+ /**
3054
+ * Pointer to the org's RFC 8414 authorization-server metadata. This is the
3055
+ * ONLY thing the platform owns and serves — discovery content (protected
3056
+ * resources, llms.txt, sitemap, API catalog, skills) is app-owned and
3057
+ * defined locally in {@link AgentReadyConfig}.
3058
+ */
2374
3059
  authorizationServer?: {
2375
3060
  issuer: string;
2376
3061
  metadataUrl: string;
2377
3062
  };
2378
- /**
2379
- * RFC 9728 protected-resource metadata objects, ready to serve. Each `metadata`
2380
- * is a complete document; `resource` is the canonical resource URI it describes.
2381
- */
2382
- protectedResources?: Array<{
2383
- resource: string;
2384
- metadata: Record<string, unknown>;
2385
- }>;
2386
- /** Org-authored llms.txt content, or null when unset. */
2387
- llmsTxt?: string | null;
2388
3063
  }
2389
3064
  /** An Agent Skill (Agent Skills Discovery RFC v0.2.0) published by this app. */
2390
3065
  interface AgentSkill {
@@ -2415,7 +3090,7 @@ interface ApiCatalogApi {
2415
3090
  /** Optional human title for the API. */
2416
3091
  title?: string;
2417
3092
  }
2418
- /** MCP Server Card (SEP-1649 / SEP-2127), advertising a live MCP server. */
3093
+ /** MCP Server Card (SEP-1649 v1.0), advertising a live MCP server. */
2419
3094
  interface McpServerCard {
2420
3095
  /** Server name. */
2421
3096
  name: string;
@@ -2425,13 +3100,103 @@ interface McpServerCard {
2425
3100
  endpoint: string;
2426
3101
  /** Transport type. Defaults to `"streamable-http"`. */
2427
3102
  transport?: string;
2428
- /** Capabilities object, e.g. `{ tools: {}, resources: {} }`. */
3103
+ /** MCP protocol version the server speaks. Defaults to `"2025-06-18"`. */
3104
+ protocolVersion?: string;
3105
+ /**
3106
+ * Capability flags. Booleans per SEP-1649 v1.0; a legacy object value
3107
+ * (e.g. `{ tools: {} }`) is normalized to booleans by presence.
3108
+ */
2429
3109
  capabilities?: Record<string, unknown>;
2430
3110
  /** Optional human description. */
2431
3111
  description?: string;
2432
3112
  /** Documentation URL. */
2433
3113
  documentationUrl?: string;
2434
3114
  }
3115
+ /** One OAuth scope an app declares in its scope catalog. */
3116
+ interface AppScope {
3117
+ /** Scope name, e.g. `designs:read`. */
3118
+ name: string;
3119
+ /** Human-readable description, shown on the consent screen. */
3120
+ description: string;
3121
+ }
3122
+ /** One skill advertised on the A2A Agent Card. */
3123
+ interface A2ACardSkill {
3124
+ id: string;
3125
+ name: string;
3126
+ description: string;
3127
+ tags?: string[];
3128
+ }
3129
+ /**
3130
+ * Overrides for the A2A Agent Card (`/.well-known/agent-card.json`). Every
3131
+ * field is optional — the card is fully derived from `site` + `skills` by
3132
+ * default. See {@link buildA2AAgentCard}.
3133
+ */
3134
+ interface A2ACardConfig {
3135
+ name?: string;
3136
+ version?: string;
3137
+ description?: string;
3138
+ /** The endpoint agents connect to. Defaults to `siteUrl`. */
3139
+ serviceUrl?: string;
3140
+ /** Transport protocol advertised for `serviceUrl`. Defaults to `'http'`. */
3141
+ transportProtocol?: string;
3142
+ /** A2A capability flags. Defaults to `{ streaming: false, pushNotifications: false }`. */
3143
+ capabilities?: Record<string, unknown>;
3144
+ /** Skills; defaults to a mapping of `config.skills` (or a generic site skill). */
3145
+ skills?: A2ACardSkill[];
3146
+ }
3147
+ /** One robots.txt policy group (a `User-agent:` block). */
3148
+ interface RobotsPolicy {
3149
+ /** User-agent(s) this group applies to, e.g. `'*'` or `'GPTBot'`. */
3150
+ userAgent: string | string[];
3151
+ /** Paths to allow, e.g. `['/']`. */
3152
+ allow?: string[];
3153
+ /** Paths to disallow, e.g. `['/api/']`. */
3154
+ disallow?: string[];
3155
+ /** Optional `Crawl-delay` (non-standard but widely honored). */
3156
+ crawlDelay?: number;
3157
+ }
3158
+ /**
3159
+ * Content Signals (https://contentsignals.org) — declares how crawlers may use
3160
+ * this site's content. Each flag renders as `<signal>=yes|no`; omitted flags
3161
+ * are not emitted (unset = no preference expressed).
3162
+ */
3163
+ interface ContentSignals {
3164
+ /** May content be indexed for search? → `search=yes|no`. */
3165
+ search?: boolean;
3166
+ /** May content be used as AI input (RAG, grounding)? → `ai-input=yes|no`. */
3167
+ aiInput?: boolean;
3168
+ /** May content be used for AI training? → `ai-train=yes|no`. */
3169
+ aiTrain?: boolean;
3170
+ }
3171
+ /** Configuration for `buildRobotsTxt`. Every field is optional. */
3172
+ interface RobotsConfig {
3173
+ /** Policy groups. Defaults to `[{ userAgent: '*', allow: ['/'] }]`. */
3174
+ policies?: RobotsPolicy[];
3175
+ /**
3176
+ * Stance toward known AI crawlers ({@link AI_BOT_USER_AGENTS}): `'allow'`
3177
+ * (default — an explicit `Allow: /` group per bot, so readiness checkers see
3178
+ * AI bots addressed), `'deny'` (a `Disallow: /` group per bot), or explicit
3179
+ * per-bot policies for finer control.
3180
+ */
3181
+ aiBots?: 'allow' | 'deny' | RobotsPolicy[];
3182
+ /** Content-Signal directive attached to the `User-agent: *` group. */
3183
+ contentSignals?: ContentSignals;
3184
+ /**
3185
+ * Sitemap URLs. Defaults to `${siteUrl}/sitemap.xml` when `config.sitemap`
3186
+ * is set; pass `[]` to emit no `Sitemap:` line.
3187
+ */
3188
+ sitemaps?: string[];
3189
+ }
3190
+ /** One URL entry for the generated sitemap.xml. */
3191
+ interface SitemapUrl {
3192
+ /** Absolute URL, or a path resolved against `siteUrl`. */
3193
+ loc: string;
3194
+ /** ISO-8601 last-modified date. */
3195
+ lastmod?: string;
3196
+ changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
3197
+ /** 0.0–1.0. */
3198
+ priority?: number;
3199
+ }
2435
3200
  /** Configuration for the agent-readiness discovery layer. */
2436
3201
  interface AgentReadyConfig {
2437
3202
  /** BuildBase server base URL, e.g. `https://api.buildbase.app` (no trailing slash needed). */
@@ -2459,6 +3224,15 @@ interface AgentReadyConfig {
2459
3224
  };
2460
3225
  /** Agent Skills to publish. Omit to skip the Agent Skills documents. */
2461
3226
  skills?: AgentSkill[];
3227
+ /**
3228
+ * The app's OAuth scope catalog — the source of truth for `scopes_supported`
3229
+ * in this app's RFC 9728 protected-resource metadata (served from your own
3230
+ * origin). Declare real, per-app scopes here (`designs:read`,
3231
+ * `render:execute`, …) instead of placeholders. A `protectedResources` entry
3232
+ * without its own `scopes` list inherits every catalog scope name. Scopes are
3233
+ * app-owned: the shared BuildBase authorization server stays scope-agnostic.
3234
+ */
3235
+ scopes?: AppScope[];
2462
3236
  /** security.txt fields (RFC 9116). Omit to skip serving security.txt. */
2463
3237
  security?: {
2464
3238
  /** Contact URI(s) — email (`mailto:`) or URL. */
@@ -2484,8 +3258,81 @@ interface AgentReadyConfig {
2484
3258
  * `buildAuthMd` generates one from the OAuth metadata + site config.
2485
3259
  */
2486
3260
  authMd?: string;
3261
+ /**
3262
+ * Local `/llms.txt` content. Takes precedence over the org-authored llms.txt
3263
+ * from the platform bundle — use when the app owns richer llms.txt content.
3264
+ */
3265
+ llmsTxt?: string;
3266
+ /**
3267
+ * Local `/llms-full.txt` content (llmstxt.org expanded document). Omit to
3268
+ * skip serving it (or serve your own static file, which then wins).
3269
+ */
3270
+ llmsFullTxt?: string;
3271
+ /**
3272
+ * A2A Agent Card served at `/.well-known/agent-card.json`. Served by
3273
+ * DEFAULT, derived from `site` + `skills`, so readiness scanners find a
3274
+ * valid card with zero config. Pass `false` to disable, or an object to
3275
+ * override any derived field.
3276
+ */
3277
+ a2aCard?: false | A2ACardConfig;
3278
+ /**
3279
+ * Web Bot Auth key directory (IETF WebBotAuth) served at
3280
+ * `/.well-known/http-message-signatures-directory`. Only for apps whose own
3281
+ * outbound bot/agent signs its requests — publish the JWKS public keys here
3282
+ * so receiving sites can verify the signatures. Omitted = not served.
3283
+ */
3284
+ webBotAuth?: {
3285
+ keys: Array<Record<string, unknown>>;
3286
+ };
3287
+ /**
3288
+ * Extra literal documents served by {@link resolveAgentPath}, keyed by exact
3289
+ * request path. The escape hatch for anything the SDK has no builder for —
3290
+ * commerce discovery (x402, UCP, ACP, MPP), `/openapi.json`, future
3291
+ * `.well-known` documents. A string value infers its content type from the
3292
+ * path extension. Extra paths take precedence over built-in documents, so
3293
+ * they can also override any SDK-generated document.
3294
+ */
3295
+ extraPaths?: Record<string, string | {
3296
+ body: string;
3297
+ contentType?: string;
3298
+ status?: number;
3299
+ cacheControl?: string;
3300
+ }>;
3301
+ /** robots.txt generation (`buildRobotsTxt`). Omitted = sane defaults. */
3302
+ robots?: RobotsConfig;
3303
+ /**
3304
+ * URLs for a minimal generated sitemap.xml (`buildSitemap`). Omit when the
3305
+ * app already generates sitemaps (e.g. next-sitemap) — the builder then
3306
+ * returns null and your own files win.
3307
+ */
3308
+ sitemap?: {
3309
+ urls: Array<string | SitemapUrl>;
3310
+ };
3311
+ /**
3312
+ * RFC 9728 protected resources this app serves, defined locally (app-owned).
3313
+ * When set, the SDK builds the `/.well-known/oauth-protected-resource`
3314
+ * document from this config — `authorization_servers` is derived from
3315
+ * `serverUrl`/`orgId` (the BuildBase issuer). Takes precedence over the
3316
+ * platform bundle. Omit to fall back to the org-configured bundle.
3317
+ */
3318
+ protectedResources?: Array<{
3319
+ /** The protected API's resource URI. Defaults to `siteUrl`. */
3320
+ resource?: string;
3321
+ /** Scopes this resource accepts (`scopes_supported`). */
3322
+ scopes?: string[];
3323
+ /** Human documentation URL (`resource_documentation`). */
3324
+ documentationUrl?: string;
3325
+ /** Bearer methods (`bearer_methods_supported`). Defaults to `['header']`. */
3326
+ bearerMethods?: string[];
3327
+ }>;
2487
3328
  /** TTL (seconds) for cached platform fetches. Default 300 (5 min). */
2488
3329
  cacheTtlSeconds?: number;
3330
+ /**
3331
+ * Timeout (ms) for platform fetches. Fail-soft on timeout, so a hung or slow
3332
+ * BuildBase server can't hang discovery routes forever. Default 5000; set `0`
3333
+ * to disable.
3334
+ */
3335
+ fetchTimeoutMs?: number;
2489
3336
  /** Injectable fetch, mainly for testing. Defaults to the global `fetch`. */
2490
3337
  fetch?: typeof fetch;
2491
3338
  }
@@ -2495,7 +3342,15 @@ interface DiscoveryDocument {
2495
3342
  contentType: string;
2496
3343
  body: string;
2497
3344
  cacheControl: string;
3345
+ /** Value for a `Vary` response header, when the body is negotiated. */
3346
+ vary?: string;
2498
3347
  }
3348
+ /**
3349
+ * User-agent strings of the known AI crawlers/agents that agent-readiness
3350
+ * checkers look for in robots.txt (`buildRobotsTxt` emits a policy group per
3351
+ * entry when `robots.aiBots` is `'allow'`/`'deny'`).
3352
+ */
3353
+ declare const AI_BOT_USER_AGENTS: readonly string[];
2499
3354
  /**
2500
3355
  * SHA-256 of `content` as `sha256:<hex>`, via the shared pure-JS hash (no Web
2501
3356
  * Crypto / Node `crypto`), so output is identical on every runtime.
@@ -2509,7 +3364,7 @@ declare function sha256Digest(content: string): string;
2509
3364
  * simply see the app as not (yet) agent-ready.
2510
3365
  */
2511
3366
  declare function fetchAgentReadiness(config: AgentReadyConfig): Promise<AgentReadinessBundle>;
2512
- /** Clear the in-memory agent-readiness cache (mainly for tests). */
3367
+ /** Clear the in-memory agent-readiness caches (mainly for tests). */
2513
3368
  declare function clearAgentReadinessCache(): void;
2514
3369
  /**
2515
3370
  * The Agent Card served at `/.well-known/agent.json`. A stable, machine-readable
@@ -2519,26 +3374,87 @@ declare function buildAgentCard(config: AgentReadyConfig, bundle: AgentReadiness
2519
3374
  /**
2520
3375
  * Resolve the RFC 9728 protected-resource metadata for a request path, or null
2521
3376
  * if no configured resource maps to it.
3377
+ *
3378
+ * App-owned. `authorization_servers` uses the platform bundle's real
3379
+ * `authorizationServer.issuer` when provided (so this doc can't advertise a
3380
+ * different issuer than the AS metadata / agent card / auth.md), falling back
3381
+ * to the `serverUrl`/`orgId` heuristic when the bundle isn't available.
2522
3382
  */
2523
- declare function buildProtectedResourceMetadata(requestPath: string, config: AgentReadyConfig, bundle: AgentReadinessBundle): DiscoveryDocument | null;
3383
+ declare function buildProtectedResourceMetadata(requestPath: string, config: AgentReadyConfig, authServerIssuer?: string): DiscoveryDocument | null;
2524
3384
  /** Agent Skills discovery index (Agent Skills Discovery RFC v0.2.0). */
2525
3385
  declare function buildAgentSkillsIndex(config: AgentReadyConfig): DiscoveryDocument | null;
2526
3386
  /** Serve a single skill's SKILL.md by request path, or null if none matches. */
2527
3387
  declare function buildSkillMd(requestPath: string, config: AgentReadyConfig): DiscoveryDocument | null;
2528
3388
  /** security.txt (RFC 9116), or null when not configured. */
2529
3389
  declare function buildSecurityTxt(config: AgentReadyConfig): DiscoveryDocument | null;
2530
- /** The org-authored llms.txt, or null when the org hasn't set one. */
2531
- declare function buildLlmsTxt(config: AgentReadyConfig, bundle: AgentReadinessBundle): DiscoveryDocument | null;
3390
+ /**
3391
+ * The `/llms.txt` document from `config.llmsTxt` (app-authored). Returns null
3392
+ * when not set — serve your own static file instead. llms.txt is app content,
3393
+ * not platform-managed.
3394
+ */
3395
+ declare function buildLlmsTxt(config: AgentReadyConfig): DiscoveryDocument | null;
3396
+ /**
3397
+ * The `/llms-full.txt` document from `config.llmsFullTxt` (app-authored).
3398
+ * Returns null when not set — serve your own static file instead.
3399
+ */
3400
+ declare function buildLlmsFullTxt(config: AgentReadyConfig): DiscoveryDocument | null;
3401
+ /**
3402
+ * A2A Agent Card (https://a2a-protocol.org) for `/.well-known/agent-card.json`.
3403
+ * Served by default, fully derived from `site` + `skills`, so a consumer is
3404
+ * A2A-discoverable with zero config; `config.a2aCard` overrides any field or
3405
+ * disables the card entirely (`false`). Skills fall back to a generic
3406
+ * site-content skill when none are configured — the card must carry at least
3407
+ * one skill to validate.
3408
+ */
3409
+ declare function buildA2AAgentCard(config: AgentReadyConfig): DiscoveryDocument | null;
3410
+ /**
3411
+ * Web Bot Auth key directory (JWKS) for
3412
+ * `/.well-known/http-message-signatures-directory`. Returns null unless
3413
+ * `config.webBotAuth.keys` is set — signing keys are the app's own and can't
3414
+ * be derived.
3415
+ */
3416
+ declare function buildWebBotAuthDirectory(config: AgentReadyConfig): DiscoveryDocument | null;
3417
+ /** One DNS record the org should publish for DNS-AID agent discovery. */
3418
+ interface DnsAidRecord {
3419
+ /** Fully-qualified record name, e.g. `_a2a._agents.example.com`. */
3420
+ name: string;
3421
+ /** Record type — HTTPS for HTTPS endpoints, SVCB otherwise. */
3422
+ type: 'HTTPS' | 'SVCB';
3423
+ ttl: number;
3424
+ /** Record data, e.g. `1 example.com. alpn="h2" port=443`. */
3425
+ data: string;
3426
+ }
3427
+ /**
3428
+ * DNS-AID (DNS for AI Discovery) records this app should publish under its
3429
+ * domain's `_agents` namespace. DNS records can't be served over HTTP — hand
3430
+ * these to the org's DNS provider (and DNSSEC-sign the zone). Derived from the
3431
+ * same config as the HTTP discovery surface, so the two never disagree.
3432
+ */
3433
+ declare function buildDnsAidRecords(config: AgentReadyConfig): DnsAidRecord[];
2532
3434
  /**
2533
3435
  * API Catalog (RFC 9727) as a `linkset+json` document for
2534
3436
  * `/.well-known/api-catalog`. Returns null when no APIs are configured.
2535
3437
  */
2536
3438
  declare function buildApiCatalog(config: AgentReadyConfig): DiscoveryDocument | null;
2537
3439
  /**
2538
- * MCP Server Card (SEP-1649) for `/.well-known/mcp/server-card.json`. Returns
2539
- * null when no card is configured (i.e. no MCP server is running).
3440
+ * MCP Server Card (SEP-1649 v1.0) for `/.well-known/mcp/server-card.json`.
3441
+ * Returns null when no card is configured (i.e. no MCP server is running).
2540
3442
  */
2541
3443
  declare function buildMcpServerCard(config: AgentReadyConfig): DiscoveryDocument | null;
3444
+ /**
3445
+ * MCP discovery manifest (SEP-1960) for `/.well-known/mcp.json` — the
3446
+ * origin-level index of every MCP server this app exposes. Complements the
3447
+ * per-server card (SEP-1649): scanners and agents probe this path first, then
3448
+ * follow `server_card` for detail. Returns null when no MCP server is
3449
+ * configured.
3450
+ *
3451
+ * The transport endpoint may live on a different origin than the app serving
3452
+ * this manifest (e.g. card on `www.`, server on `api.`); the `authentication`
3453
+ * pointer is derived from the ENDPOINT's origin per RFC 9728 path derivation,
3454
+ * so agents land on the metadata the server's own WWW-Authenticate challenge
3455
+ * advertises.
3456
+ */
3457
+ declare function buildMcpDiscoveryManifest(config: AgentReadyConfig): DiscoveryDocument | null;
2542
3458
  /**
2543
3459
  * The `/auth.md` document (agent registration + authentication instructions).
2544
3460
  * Uses `config.authMd` verbatim when provided; otherwise generates one from the
@@ -2546,6 +3462,42 @@ declare function buildMcpServerCard(config: AgentReadyConfig): DiscoveryDocument
2546
3462
  * there is nothing to describe (no authorizationServer and no override).
2547
3463
  */
2548
3464
  declare function buildAuthMd(config: AgentReadyConfig, bundle: AgentReadinessBundle): DiscoveryDocument | null;
3465
+ /**
3466
+ * robots.txt with AI-bot policy groups, Content Signals, and sitemap
3467
+ * references. Always returns a document — with no `config.robots` it emits an
3468
+ * allow-all default policy plus an explicit `Allow: /` group per known AI bot.
3469
+ */
3470
+ declare function buildRobotsTxt(config: AgentReadyConfig): DiscoveryDocument;
3471
+ /**
3472
+ * A minimal sitemap.xml from `config.sitemap.urls`, or null when not
3473
+ * configured. Meant for API-first apps that would otherwise have no sitemap —
3474
+ * apps with real content pipelines (e.g. next-sitemap) should keep those and
3475
+ * omit `config.sitemap`.
3476
+ */
3477
+ declare function buildSitemap(config: AgentReadyConfig): DiscoveryDocument | null;
3478
+ /**
3479
+ * True when an `Accept` header prefers markdown (`text/markdown` /
3480
+ * `text/x-markdown`) over `text/html` — q-value aware, so
3481
+ * `text/html;q=0.5, text/markdown` is markdown but `text/markdown;q=0.1,
3482
+ * text/html` is not. A bare wildcard does not count as a markdown preference.
3483
+ */
3484
+ declare function wantsMarkdown(acceptHeader: string | null | undefined): boolean;
3485
+ /**
3486
+ * Markdown content negotiation: pick the markdown or HTML variant of a page
3487
+ * per the `Accept` header. The returned document carries `vary: 'Accept'` —
3488
+ * forward it so caches key on the header.
3489
+ */
3490
+ declare function negotiateMarkdown(acceptHeader: string | null | undefined, variants: {
3491
+ html: string;
3492
+ markdown: string;
3493
+ }, config?: Pick<AgentReadyConfig, 'cacheTtlSeconds'>): DiscoveryDocument;
3494
+ /**
3495
+ * Value for a `Link` response header advertising this app's discovery
3496
+ * documents (llms.txt, Agent Card, and — when configured — sitemap, API
3497
+ * catalog, MCP server card). Sync and pure (no platform fetch), so it's safe
3498
+ * in edge middleware.
3499
+ */
3500
+ declare function buildDiscoveryLinkHeader(config: AgentReadyConfig): string;
2549
3501
  /**
2550
3502
  * Resolve any `.well-known` request path to its discovery document, or null if
2551
3503
  * this app serves nothing there (caller should 404).
@@ -2554,10 +3506,18 @@ declare function buildAuthMd(config: AgentReadyConfig, bundle: AgentReadinessBun
2554
3506
  * oauth-authorization-server (pointer), agent-skills index + SKILL.md,
2555
3507
  * security.txt, api-catalog (RFC 9727), and the MCP server card.
2556
3508
  *
2557
- * Root-level docs are served via their own builders (they aren't under
2558
- * `.well-known`): `buildLlmsTxt` for `/llms.txt` and `buildAuthMd` for `/auth.md`.
3509
+ * Root-level docs (`/robots.txt`, `/llms.txt`, `/auth.md`, …) are not handled
3510
+ * here — use {@link resolveAgentPath}, which covers both, for new wiring.
2559
3511
  */
2560
3512
  declare function resolveWellKnown(requestPath: string, config: AgentReadyConfig): Promise<DiscoveryDocument | null>;
3513
+ /**
3514
+ * Superset of {@link resolveWellKnown}: resolves ANY agent-facing path — the
3515
+ * root-level documents (`/robots.txt`, `/sitemap.xml`, `/llms.txt`,
3516
+ * `/auth.md`, `/security.txt`) plus everything under `/.well-known/*`. One
3517
+ * catch-all (or middleware) wired to this function covers the app's entire
3518
+ * agent-readiness surface. Returns null for paths this app doesn't serve.
3519
+ */
3520
+ declare function resolveAgentPath(requestPath: string, config: AgentReadyConfig): Promise<DiscoveryDocument | null>;
2561
3521
  /** A WebMCP tool definition exposed to in-page agents via `navigator.modelContext`. */
2562
3522
  interface WebMcpTool {
2563
3523
  name: string;
@@ -2644,6 +3604,13 @@ interface AppTokenRequestClaims {
2644
3604
  resource?: string[];
2645
3605
  /** The OAuth2 client's display title. */
2646
3606
  clientTitle?: string;
3607
+ /**
3608
+ * Per-user BuildBase session bound to this grant. Embed it ENCRYPTED in the
3609
+ * token you mint (JWTs are signed, not encrypted) and never store it — your
3610
+ * MCP/agent endpoints decrypt it per request to call BuildBase as this user
3611
+ * (`buildbase.withSession(...)`). Fresh on every grant, including refresh.
3612
+ */
3613
+ sessionId?: string;
2647
3614
  [claim: string]: unknown;
2648
3615
  }
2649
3616
  /** The payload BuildBase sends to `applicationRevokeUrl`. */
@@ -2653,14 +3620,40 @@ interface AppRevokeRequestClaims {
2653
3620
  reason: string;
2654
3621
  [claim: string]: unknown;
2655
3622
  }
3623
+ /** Options for {@link verifyClientJwt} (all optional; secure defaults). */
3624
+ interface VerifyClientJwtOptions {
3625
+ /** Allowed clock skew in seconds for `exp`/`nbf`. Default 60. */
3626
+ clockToleranceSec?: number;
3627
+ /**
3628
+ * Require a numeric `exp` claim. Default **true** — a JWT with no expiry
3629
+ * would never expire, so a leaked token stays valid forever. Set `false`
3630
+ * only for a token type you know is intentionally non-expiring.
3631
+ */
3632
+ requireExp?: boolean;
3633
+ /** If set, `iss` must equal this value (RFC 7519 issuer check). */
3634
+ issuer?: string;
3635
+ /** If set, `aud` must equal (or, for an array `aud`, include) this value. */
3636
+ audience?: string;
3637
+ }
2656
3638
  /**
2657
3639
  * Verify a BuildBase-issued HS256 JWT (signed with the client secret) and return
2658
- * its payload. Checks the signature (timing-safe), the algorithm, and `exp`/`nbf`.
3640
+ * its payload. Checks the signature (timing-safe), the algorithm, `exp`/`nbf`,
3641
+ * and — by default — that an `exp` is present at all. Optionally pins `iss`/`aud`.
2659
3642
  * Throws {@link AppBridgeError} on any failure.
2660
3643
  */
2661
- declare function verifyClientJwt(token: string, clientSecret: string, clockToleranceSec?: number): Record<string, any>;
3644
+ declare function verifyClientJwt(token: string, clientSecret: string, options?: VerifyClientJwtOptions): Record<string, any>;
2662
3645
  /** Extract the token from an `Authorization: Bearer <token>` header. */
2663
3646
  declare function extractBearerToken(authorization: string | null | undefined): string | null;
3647
+ /**
3648
+ * Sign an HS256 JWT — the symmetric counterpart of {@link verifyClientJwt}.
3649
+ * Sets `iat` and `exp` (from `expiresInSec`, default 3600) unless the payload
3650
+ * already carries them. The intended use is minting the app's own agent access
3651
+ * tokens in an `applicationTokenUrl` handler, embedding whatever claims the
3652
+ * MCP/API layer needs to verify later (e.g. `sub`, `scope`, a session id).
3653
+ */
3654
+ declare function signClientJwt(payload: Record<string, unknown>, secret: string, options?: {
3655
+ expiresInSec?: number;
3656
+ }): string;
2664
3657
  interface VerifyOptions {
2665
3658
  /** The `Authorization` header value from the incoming request. */
2666
3659
  authorization: string | null | undefined;
@@ -2735,20 +3728,6 @@ declare function handleAppRevokeRequest(options: {
2735
3728
  success: boolean;
2736
3729
  message?: string;
2737
3730
  }>>;
2738
- /**
2739
- * Build the 401 an agent should receive when it calls your protected API without
2740
- * a valid token. The `WWW-Authenticate: Bearer resource_metadata=...` header
2741
- * points the agent at your `/.well-known/oauth-protected-resource` document,
2742
- * bootstrapping the OAuth discovery flow (RFC 9728 §5.1, RFC 6750 §3).
2743
- *
2744
- * @example
2745
- * ```ts
2746
- * if (!isValid(token)) {
2747
- * const c = bearerChallenge({ resourceMetadataUrl: "https://imejis.io/.well-known/oauth-protected-resource" });
2748
- * res.writeHead(c.status, c.headers).end(c.body);
2749
- * }
2750
- * ```
2751
- */
2752
3731
  declare function bearerChallenge(options: {
2753
3732
  resourceMetadataUrl: string;
2754
3733
  error?: 'invalid_token' | 'insufficient_scope' | string;
@@ -3043,5 +4022,198 @@ interface BuildBaseResult extends ScopedActions {
3043
4022
  }
3044
4023
  declare function BuildBase(config: BuildBaseConfig): BuildBaseResult;
3045
4024
 
3046
- export { ApiVersion, AppBridgeError, AuthApi, AuthStatus, BBAction, BBScreen, BBStatus, BB_PARAM, BaseApi, BetaForm, BillingIntervals, BuildBase, CURRENCY_DISPLAY, CURRENCY_FLAG, CreditBucketSource, CreditBucketStatus, CreditTransactionType, DEFAULT_ROLE_PERMISSIONS, DunningState, EventEmitter, InvoiceStatuses, PLAN_CURRENCY_CODES, PLAN_CURRENCY_OPTIONS, PUSH_SERVICE_WORKER_SCRIPT, Permission, PushApi, SDKEvent, SettingsApi, SubscriptionItemType, SubscriptionStatus, UserApi, WorkspaceApi, appTokenFailure, appTokenSuccess, bearerChallenge, buildAgentCard, buildAgentSkillsIndex, buildApiCatalog, buildAuthMd, buildLlmsTxt, buildMcpServerCard, buildProtectedResourceMetadata, buildSecurityTxt, buildSkillMd, calculateBillableSeats, calculateSeatOverageCents, calculateTotalSubscriptionCents, cleanBBParams, clearAgentReadinessCache, clearAuthIntent, consumeAuthIntent, createBBUrl, createCheckoutRedirectUrls, createCreditPurchaseRedirectUrls, BuildBase as default, eventEmitter, extractBearerToken, fetchAgentReadiness, formatCents, formatOverageRate, formatOverageRateWithLabel, formatQuotaIncludedOverage, formatQuotaWithPrice, getAvailableCurrenciesFromPlans, getBasePriceCents, getBillingIntervalAndCurrencyFromPriceId, getCurrencyFlag, getCurrencySymbol, getDisplayCurrency, getPerSeatPriceCents, getPricingVariant, getQuotaDisplayValue, getQuotaDisplayWithVariant, getQuotaOverageCents, getQuotaUnitLabelFromName, getSeatPricing, getStripePriceIdForInterval, handleAppRevokeRequest, handleAppTokenRequest, hasPermission, invalidateCreditBalance, invalidateQuotaUsage, invalidateSubscription, parseWebhookEvent, provideWebMcpTools, readBBParams, resolveMaxUsers, resolvePermissions, resolveWellKnown, safeRedirect, saveAuthIntent, sha256Digest, validateInvite, validateRedirectUrl, verifyAppRevokeRequest, verifyAppTokenRequest, verifyClientJwt, verifyWebhookSignature };
3047
- export type { AgentReadinessBundle, AgentReadyConfig, AgentSkill, ApiCatalogApi, AppRevokeRequestClaims, AppTokenRequestClaims, AppTokenResponseBody, AppTokenResult, BBActionType, BBScreenType, BBStatusType, BetaFormData, BetaFormResponse, BillingInterval, BuildBaseConfig, BuildBaseResult, BuildBaseSession, CheckoutResult, CreditActions, CreditBucketSourceType, CreditBucketStatusType, CreditTransactionTypeValue, DiscoveryDocument, DunningStateType, EventData, EventType, FeatureActions, FormatQuotaWithPriceOptions, GetCheckoutStripeParams, HandlerResult, IAllQuotaUsageResponse, IBaseApiConfig, IBasePricing, IBetaConfig, ICheckoutSessionRequest, ICheckoutSessionResponse, ICheckoutStripeOptions, IConsumeCreditsRequest, IConsumeCreditsResponse, ICreditBalance, ICreditBucket, ICreditBucketsQuery, ICreditBucketsResponse, ICreditPackage, ICreditPackagePricingVariant, ICreditPurchaseRequest, ICreditPurchaseResponse, ICreditTransaction, ICreditTransactionsQuery, ICreditTransactionsResponse, IEventCallbacks, IExpiringCreditsResponse, IInvoice, IInvoiceListResponse, IInvoiceResponse, IOsConfig, IOsState, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPricingVariant, IPublicCreditPackage, IPublicCreditPackagesResponse, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaOveragePriceIdsByInterval, IQuotaOveragesByInterval, IQuotaUsageStatus, IQuotaUsageStatusResponse, IRecordUsageRequest, IRecordUsageResponse, IStripePricesByInterval, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, IUsageLogEntry, IUsageLogsQuery, IUsageLogsResponse, InviteBlockReason, InviteValidation, InvoiceActions, InvoiceStatus, InvoiceStatusType, MaxUsersConfig, McpServerCard, NotificationData, NotificationEvent, NotificationResult, OnWorkspaceChangeParams, PermissionActions, PermissionContext, PermissionKey, PlanActions, PlanVersionWithPricingVariants, QuotaDisplayValue, QuotaDisplayWithOverage, RolePermissionMap, ScopedActions, SettingsActions, SubscriptionActions, SubscriptionItemTypeValue, SubscriptionStatusType, UsageActions, UserActions, UserCreatedEventData, UserUpdatedEventData, WebMcpTool, WorkspaceActions, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };
4025
+ /**
4026
+ * MCP server toolkit (server-side, framework-agnostic).
4027
+ *
4028
+ * Turns a consuming app into a live MCP (Model Context Protocol) server so AI
4029
+ * agents can operate its BuildBase capabilities — workspaces, subscriptions,
4030
+ * quotas, credits, feature flags, permissions — plus any custom tools the app
4031
+ * defines. The transport is stateless Streamable HTTP: a single JSON-RPC
4032
+ * message per POST, no sessions and no SSE, which keeps the handler pure and
4033
+ * identical on Node 18+, edge, Deno, and Bun.
4034
+ *
4035
+ * Zero framework types: the core `handle()` takes a plain
4036
+ * `{ method, headers, body }` and returns `{ status, headers, body }` (wire it
4037
+ * into Express/Fastify/Hono yourself), while `fetch()` adapts Web-standard
4038
+ * `Request` → `Response` for Next.js App Router and edge runtimes.
4039
+ *
4040
+ * Agents authenticate with the Bearer tokens the app mints via the OAuth2
4041
+ * app-bridge (`handleAppTokenRequest` + `signClientJwt`); the `auth.verify`
4042
+ * callback maps a verified token to the BuildBase session the tools run under.
4043
+ *
4044
+ * @example Next.js App Router — the entire integration:
4045
+ * ```ts
4046
+ * // lib/mcp.ts
4047
+ * import BuildBase from '@buildbase/sdk';
4048
+ * import { createMcpHandler, verifyClientJwt } from '@buildbase/sdk/mcp';
4049
+ *
4050
+ * const buildbase = BuildBase({
4051
+ * serverUrl: process.env.BUILDBASE_URL!,
4052
+ * orgId: process.env.BUILDBASE_ORG_ID!,
4053
+ * });
4054
+ *
4055
+ * export const mcp = createMcpHandler({
4056
+ * buildbase,
4057
+ * serverInfo: { name: 'imejis', version: '1.0.0' },
4058
+ * auth: {
4059
+ * verify: (token) => {
4060
+ * const c = verifyClientJwt(token, process.env.BUILDBASE_CLIENT_SECRET!);
4061
+ * return { sessionId: String(c.sid), userId: String(c.sub), scopes: c.scope };
4062
+ * },
4063
+ * resourceMetadataUrl: 'https://imejis.io/.well-known/oauth-protected-resource',
4064
+ * },
4065
+ * });
4066
+ *
4067
+ * // app/api/mcp/route.ts
4068
+ * import { mcp } from '@/lib/mcp';
4069
+ * export const POST = (req: Request) => mcp.fetch(req);
4070
+ * export const GET = (req: Request) => mcp.fetch(req); // 405 per spec (no SSE)
4071
+ * export const DELETE = (req: Request) => mcp.fetch(req); // 405 (stateless)
4072
+ * ```
4073
+ */
4074
+
4075
+ /** A transport-agnostic HTTP request (mirror of the DiscoveryDocument idea). */
4076
+ interface McpHttpRequest {
4077
+ /** HTTP method, e.g. `'POST'`. */
4078
+ method: string;
4079
+ /** Header map. Keys are matched case-insensitively. */
4080
+ headers: Record<string, string | undefined>;
4081
+ /** Raw JSON body string, or an already-parsed value (e.g. Express req.body). */
4082
+ body?: string | unknown;
4083
+ }
4084
+ /** The identity a verified Bearer token resolves to. */
4085
+ interface McpAuthInfo {
4086
+ /** BuildBase session all tool calls run under (`buildbase.withSession(...)`). */
4087
+ sessionId: string;
4088
+ /** The acting BuildBase user id — default subject for permission checks. */
4089
+ userId?: string;
4090
+ /** Pin tools to one workspace; used when the agent omits `workspaceId`. */
4091
+ workspaceId?: string;
4092
+ /** OAuth scopes granted to the agent; filters tools with `requiredScopes`. */
4093
+ scopes?: string[];
4094
+ /** Raw verified claims, passed through to tool context. */
4095
+ claims?: Record<string, unknown>;
4096
+ }
4097
+
4098
+ /**
4099
+ * BuildBase agent-auth presets (server-side, framework-agnostic).
4100
+ *
4101
+ * The BuildBase security model: the platform runs the OAuth2 flow (login,
4102
+ * consent, PKCE, refresh) but the APP mints and verifies its own user tokens,
4103
+ * signed with the app's own secret. The platform only relays the minted token
4104
+ * to the agent — it never sees the secret, so it can neither forge nor decode
4105
+ * an app token. The per-user BuildBase session travels inside the token only
4106
+ * as an AES-256-GCM-encrypted `sid` claim, so it is never stored and never
4107
+ * plaintext anywhere; access to it expires with the token.
4108
+ *
4109
+ * These presets make that model a one-liner on each side of the flow, and run
4110
+ * entirely in the app's process — pure local crypto, zero platform calls:
4111
+ *
4112
+ * • {@link mintAgentToken} — inside your `applicationTokenUrl` handler:
4113
+ * signs the app JWT (HS256) with your secret, stamps `aud` from the RFC
4114
+ * 8707 resource, and embeds the encrypted `sid` automatically.
4115
+ * • {@link buildbaseAuth} — the `auth` config for `createMcpHandler`:
4116
+ * verifies the JWT, enforces audience binding, decrypts the `sid`, and
4117
+ * maps the claims to `McpAuthInfo`.
4118
+ *
4119
+ * @example The full loop:
4120
+ * ```ts
4121
+ * // applicationTokenUrl route — the platform calls this on every grant
4122
+ * const { status, body } = await handleAppTokenRequest({
4123
+ * authorization: req.headers.get("authorization"),
4124
+ * clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
4125
+ * mintToken: (claims) => mintAgentToken({ claims, secret: process.env.SYSTEM_SECRET! }),
4126
+ * });
4127
+ *
4128
+ * // MCP server — verifies what the route above minted
4129
+ * const mcp = createMcpHandler({
4130
+ * buildbase,
4131
+ * auth: buildbaseAuth({ secret: process.env.SYSTEM_SECRET!, resource: "https://app.example.com/api/mcp" }),
4132
+ * });
4133
+ * ```
4134
+ *
4135
+ * AES-GCM comes from WebCrypto (`globalThis.crypto.subtle`) — Node 18+, Bun,
4136
+ * Deno, edge runtimes, browsers. The wire format is
4137
+ * `base64url(iv(12) || authTag(16) || ciphertext)` with the key derived as
4138
+ * `SHA-256(secret + ":bb-session")`, byte-compatible with Node
4139
+ * `createCipheriv("aes-256-gcm", ...)` implementations of the same layout.
4140
+ */
4141
+
4142
+ /** Encrypt/decrypt pair for the `sid` claim, bound to one app secret. */
4143
+ interface SessionRefCrypto {
4144
+ /** Encrypt a BuildBase session id for embedding in an app JWT. */
4145
+ encryptSessionRef(sessionId: string): Promise<string>;
4146
+ /** Decrypt a `sid` claim. Returns null on any failure (wrong key, garbage). */
4147
+ decryptSessionRef(ref: string): Promise<string | null>;
4148
+ }
4149
+ /**
4150
+ * Session-ref crypto derived from the app's secret. Both sides of the loop
4151
+ * ({@link mintAgentToken}, {@link buildbaseAuth}) use this internally — reach
4152
+ * for it directly only when minting or verifying tokens by hand.
4153
+ */
4154
+ declare function createSessionRefCrypto(secret: string): SessionRefCrypto;
4155
+ /** Options for {@link mintAgentToken}. */
4156
+ interface MintAgentTokenOptions {
4157
+ /** The verified platform claims (from `handleAppTokenRequest`'s callback). */
4158
+ claims: AppTokenRequestClaims;
4159
+ /** The APP's token-signing secret. Never leaves this process. */
4160
+ secret: string;
4161
+ /** Token lifetime in seconds. Default 3600 — keep agent tokens short-lived. */
4162
+ expiresInSec?: number;
4163
+ /**
4164
+ * App-specific claims merged into the token — e.g. a `workspaceId` resolved
4165
+ * by your own user sync. Merged last, so they can override the defaults.
4166
+ */
4167
+ extraClaims?: Record<string, unknown>;
4168
+ }
4169
+ /**
4170
+ * Mint the app's agent access token from a platform grant: HS256-signed with
4171
+ * YOUR secret, `aud` bound to the granted RFC 8707 resource(s), scopes carried
4172
+ * through, and the per-user BuildBase session embedded as an encrypted `sid`
4173
+ * claim. The result plugs straight into `handleAppTokenRequest`'s `mintToken`.
4174
+ */
4175
+ declare function mintAgentToken(options: MintAgentTokenOptions): Promise<{
4176
+ token: string;
4177
+ expiresIn: number;
4178
+ }>;
4179
+ /** Options for {@link buildbaseAuth}. */
4180
+ interface BuildBaseAuthOptions {
4181
+ /** The APP's token-signing secret — the same one `mintAgentToken` used. */
4182
+ secret: string;
4183
+ /**
4184
+ * The protected resource(s) this server IS. Enforces RFC 8707 audience
4185
+ * binding — the token's `aud` must include one of these URIs. Pass an array
4186
+ * when the server is addressable under more than one resource identifier
4187
+ * (e.g. the canonical `<host>/mcp` plus the literal endpoint URL); the
4188
+ * FIRST entry is the canonical one used to derive `resourceMetadataUrl`.
4189
+ */
4190
+ resource?: string | string[];
4191
+ /**
4192
+ * Explicit RFC 9728 metadata URL for the 401 challenge. Defaults to the
4193
+ * path-derived `/.well-known/oauth-protected-resource<path>` of the first
4194
+ * `resource`.
4195
+ */
4196
+ resourceMetadataUrl?: string;
4197
+ /**
4198
+ * Reject tokens that carry no `aud` claim at all. Default false: audience is
4199
+ * enforced when present, and legacy audience-less tokens still work. Turn
4200
+ * this on once every minted token is audience-bound.
4201
+ */
4202
+ requireAudience?: boolean;
4203
+ /** Extra JWT verification options (clock tolerance, issuer pinning). */
4204
+ verify?: Pick<VerifyClientJwtOptions, 'clockToleranceSec' | 'issuer'>;
4205
+ }
4206
+ /**
4207
+ * The `auth` config for `createMcpHandler`, prewired for BuildBase-minted app
4208
+ * tokens: HS256 verification with your secret, RFC 8707 audience binding,
4209
+ * `sid` decryption to the BuildBase session, claim mapping to `McpAuthInfo`,
4210
+ * and the derived RFC 9728 `resourceMetadataUrl`. Entirely local — the token
4211
+ * and secret never leave this process.
4212
+ */
4213
+ declare function buildbaseAuth(options: BuildBaseAuthOptions): {
4214
+ verify: (token: string, req: McpHttpRequest) => Promise<McpAuthInfo | null>;
4215
+ resourceMetadataUrl?: string;
4216
+ };
4217
+
4218
+ export { AI_BOT_USER_AGENTS, ApiVersion, AppBridgeError, AuthApi, AuthStatus, BBAction, BBScreen, BBStatus, BB_PARAM, BaseApi, BetaForm, BillingIntervals, BuildBase, CURRENCY_DISPLAY, CURRENCY_FLAG, CreditBucketSource, CreditBucketStatus, CreditTransactionType, DEFAULT_ROLE_PERMISSIONS, DunningState, EventEmitter, InvoiceStatuses, PLAN_CURRENCY_CODES, PLAN_CURRENCY_OPTIONS, PUSH_SERVICE_WORKER_SCRIPT, Permission, PushApi, SDKEvent, SettingsApi, SubscriptionItemType, SubscriptionStatus, UserApi, WorkspaceApi, appTokenFailure, appTokenSuccess, bearerChallenge, buildA2AAgentCard, buildAgentCard, buildAgentSkillsIndex, buildApiCatalog, buildAuthMd, buildDiscoveryLinkHeader, buildDnsAidRecords, buildLlmsFullTxt, buildLlmsTxt, buildMcpDiscoveryManifest, buildMcpServerCard, buildProtectedResourceMetadata, buildRobotsTxt, buildSecurityTxt, buildSitemap, buildSkillMd, buildWebBotAuthDirectory, buildbaseAuth, calculateBillableSeats, calculateSeatOverageCents, calculateTotalSubscriptionCents, cleanBBParams, clearAgentReadinessCache, clearAuthIntent, consumeAuthIntent, createBBUrl, createCheckoutRedirectUrls, createCreditPurchaseRedirectUrls, createSessionRefCrypto, BuildBase as default, eventEmitter, extractBearerToken, fetchAgentReadiness, formatCents, formatOverageRate, formatOverageRateWithLabel, formatQuotaIncludedOverage, formatQuotaWithPrice, getAvailableCurrenciesFromPlans, getBasePriceCents, getBillingIntervalAndCurrencyFromPriceId, getCurrencyFlag, getCurrencySymbol, getDisplayCurrency, getPerSeatPriceCents, getPricingVariant, getQuotaDisplayValue, getQuotaDisplayWithVariant, getQuotaOverageCents, getQuotaUnitLabelFromName, getSeatPricing, getStripePriceIdForInterval, handleAppRevokeRequest, handleAppTokenRequest, hasPermission, invalidateCreditBalance, invalidateQuotaUsage, invalidateSubscription, isZeroDecimalCurrency, minorAmountToDisplay, mintAgentToken, negotiateMarkdown, parseWebhookEvent, provideWebMcpTools, readBBParams, resolveAgentPath, resolveMaxUsers, resolvePermissions, resolveWellKnown, safeRedirect, saveAuthIntent, sha256Digest, signClientJwt, validateInvite, validateRedirectUrl, verifyAppRevokeRequest, verifyAppTokenRequest, verifyClientJwt, verifyWebhookSignature, wantsMarkdown };
4219
+ export type { A2ACardConfig, A2ACardSkill, AgentReadinessBundle, AgentReadyConfig, AgentSkill, ApiCatalogApi, AppRevokeRequestClaims, AppScope, AppTokenRequestClaims, AppTokenResponseBody, AppTokenResult, BBActionType, BBScreenType, BBStatusType, BetaFormData, BetaFormResponse, BillingInterval, BuildBaseAuthOptions, BuildBaseConfig, BuildBaseResult, BuildBaseSession, CheckoutResult, ContentSignals, CreditActions, CreditBucketSourceType, CreditBucketStatusType, CreditTransactionTypeValue, DiscoveryDocument, DnsAidRecord, DunningStateType, EventData, EventType, FeatureActions, FormatQuotaWithPriceOptions, GetCheckoutStripeParams, HandlerResult, IAllQuotaUsageResponse, IBaseApiConfig, IBasePricing, IBetaConfig, ICheckoutSessionRequest, ICheckoutSessionResponse, ICheckoutStripeOptions, IConsumeCreditsRequest, IConsumeCreditsResponse, ICreditBalance, ICreditBucket, ICreditBucketsQuery, ICreditBucketsResponse, ICreditPackage, ICreditPackagePricingVariant, ICreditPurchaseRequest, ICreditPurchaseResponse, ICreditTransaction, ICreditTransactionsQuery, ICreditTransactionsResponse, IEventCallbacks, IExpiringCreditsResponse, IInvoice, IInvoiceListResponse, IInvoiceResponse, IOsConfig, IOsState, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPricingVariant, IPublicCreditPackage, IPublicCreditPackagesResponse, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaOveragePriceIdsByInterval, IQuotaOveragesByInterval, IQuotaUsageStatus, IQuotaUsageStatusResponse, IRecordUsageRequest, IRecordUsageResponse, ISettings, IStripePricesByInterval, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, IUsageLogEntry, IUsageLogsQuery, IUsageLogsResponse, IUser, IWorkspace, InviteBlockReason, InviteValidation, InvoiceActions, InvoiceStatus, InvoiceStatusType, MaxUsersConfig, McpServerCard, MintAgentTokenOptions, NotificationData, NotificationEvent, NotificationResult, OnWorkspaceChangeParams, PermissionActions, PermissionContext, PermissionKey, PlanActions, PlanVersionWithPricingVariants, QuotaDisplayValue, QuotaDisplayWithOverage, RedirectValidationOptions, RobotsConfig, RobotsPolicy, RolePermissionMap, ScopedActions, SessionRefCrypto, SettingsActions, SitemapUrl, SubscriptionActions, SubscriptionItemTypeValue, SubscriptionStatusType, TranslationKey, UsageActions, UserActions, UserCreatedEventData, UserUpdatedEventData, WebMcpTool, WorkspaceActions, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };