oblien 2.7.1 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/billing.md CHANGED
@@ -1,4 +1,149 @@
1
- # Namespace billing
1
+ # Compute and namespace billing
2
+
3
+ ## PAYG and prepaid monthly capacity
4
+
5
+ Hobby, Pro and Scale remain credit subscriptions: they fund the existing owner
6
+ wallet and set its resource tier. Spend that wallet on measured `payg` usage or
7
+ a prepaid `monthly` resource pool. A monthly purchase does not create a second
8
+ spendable balance. Stripe and wallet funds are payment sources. Both modes share the billing contract, resource enforcement, usage
9
+ ledger and signed billing events. Direct capacity purchases are available to
10
+ the account owner; hosting a customer checkout through reseller `offer` still
11
+ requires an Enterprise owner.
12
+
13
+ A subscription belongs to its personal or namespace resource pool, never to a
14
+ VM ID. One or many VMs can share it; confirmed deletion frees allocations without
15
+ renewing or canceling the pool. Retained disks still consume storage. Each scope
16
+ has one current capacity contract and one mode. Use separate namespaces for
17
+ independent pools; they cannot borrow each other’s capacity. New pools share the
18
+ owner tier’s global limits, so separate namespaces cannot multiply the account
19
+ allowance. Monthly reservations consume that budget even when idle.
20
+
21
+ New contracts report `allocationBasis: "running"`: confirmed stopped and hibernated
22
+ VMs release running CPU/RAM, while retained disks, workspace slots and configured
23
+ owned resources still count. Paused VMs and unresolved operations retain their
24
+ running reservation. The account per-workspace limit and 12-vCPU platform ceiling
25
+ still apply. Explicit namespace `max_total_*` policy remains an allocated ceiling.
26
+ Already-sold contracts report `allocated` and retain their original scope and
27
+ prices; this release does not change their purchased rights.
28
+
29
+ PAYG uses the existing wallet balance and ordinary one-time wallet deposits.
30
+ Adding funds does not raise resource limits. The catalog's optional
31
+ `walletFunding` amounts and each preset's `paygEstimate.computeHourAmount` and
32
+ `storageMonthAmount` are backend-computed USD cents. Hourly examples assume all
33
+ CPU busy and all RAM allocated, before the cap; actual idle CPU can cost less.
34
+ The cap limits usage charges, not the upfront deposit amount.
35
+
36
+ For account wallet funding through `POST /credits/purchase`, send a fresh
37
+ `idempotencyKey` for each deliberate deposit and reuse it unchanged after a
38
+ timeout. Keys accept 8–128 letters, numbers, dots, colons, underscores or
39
+ hyphens. Repeating a package is a new purchase; retrying one purchase resumes
40
+ its saved checkout. This uses the existing wallet payment and fulfillment flow.
41
+
42
+ SDK 2.8.1 adds the optional-namespace signatures below. Personal workspaces are the default. Call `billing.capacity()` without an argument to read them, and pass `null` as the first argument to capacity mutation methods. Supply an exact namespace slug to manage a separate named pool. REST requests omit `namespace` or send JSON `null` for personal billing; never send the query string `namespace=null`.
43
+
44
+ ```typescript
45
+ const namespace = null; // Or a named pool's exact slug.
46
+ const current = await client.billing.capacity(namespace);
47
+ const catalog = current.catalog ?? await client.billing.capacityCatalog();
48
+ const selected = catalog.presets.find(p => p.id === 'small' && p.available !== false);
49
+ if (!selected) throw new Error('Choose a size within your account plan.');
50
+ const { quote } = await client.billing.previewCapacity(namespace, {
51
+ capacity: selected.capacity,
52
+ billingMode: 'monthly', paymentSource: 'wallet', autoRenew: false,
53
+ idempotencyKey: savedOrder.previewKey,
54
+ });
55
+ // Review backend-calculated amounts and effectiveAt before confirming.
56
+ await client.billing.confirmCapacity(namespace, {
57
+ quoteId: quote.id, idempotencyKey: savedOrder.confirmKey,
58
+ });
59
+ const { capacity, catalog: savedPrices } = await client.billing.capacity(namespace);
60
+ ```
61
+
62
+ Existing subscriptions retain their saved model after an SDK upgrade. Read `capacity(namespace)` first; a null capacity means the selected scope has not adopted the capacity contract. An existing hosted reseller subscription uses plan changes to adopt monthly capacity at renewal. A quota edit cannot perform that conversion.
63
+
64
+ For PAYG use `billingMode: 'payg'` and `paymentSource: 'wallet'`. The dashboard uses wallet payment for new pools. Explicit recurring
65
+ card integrations remain supported: use `paymentSource: 'stripe'` and confirm the saved quote with
66
+ `capacityCheckout` instead. Native Stripe Checkout is the default, with the
67
+ existing optional `allowPromotionCodes` and `checkoutMode` controls. Returning
68
+ from checkout never proves payment: inspect committed coverage and signed events.
69
+
70
+ Quotes use USD **cents**; savings use USD **dollars**. Rates and presets come from
71
+ the backend, and existing contracts return their saved-tariff catalog. Only
72
+ eligible verified paid wallet funds, including settled credit-subscription
73
+ invoices, can buy monthly coverage. `capacity().wallet.balance` and
74
+ `wallet.monthlyAvailable` are USD dollars; the latter may be lower because it
75
+ excludes gifts, test grants and unverified receipts. `accountPlan` is the owner’s
76
+ backend-derived policy, and `available` on sizing examples indicates whether the
77
+ size fits that plan. Quotes and confirmation recheck admission; these display
78
+ fields never grant resources. Namespace
79
+ allowances and promotional grants are not money. Read `computeCovered` and
80
+ `periodEnd`: a prepaid month has no additional compute-credit ceiling, and a
81
+ zero wallet cannot remove that paid compute coverage. The manual namespace
82
+ suspension and purchased resource pool still apply.
83
+
84
+ Wallet monthly renewal is opt-in through
85
+ `setCapacityAutoRenew(namespace, { autoRenew, idempotencyKey })`. Wallet changes
86
+ use the same preview and confirm methods; pending reductions can be canceled
87
+ with `cancelCapacityChange(namespace, { quoteId, idempotencyKey })`. Hosted
88
+ subscription changes use `previewPlanChange` / `changePlan`, and renewal uses
89
+ `cancelSubscription` / `resumeSubscription`. Do not start a competing checkout
90
+ for an existing live subscription. Upgrades charge the prorated difference and
91
+ preserve usage/top-ups; reductions wait for the next period. Failed payment
92
+ retains the prior plan. For new contracts, wallet renewal rechecks the current
93
+ account tier before charging; a tier change never revokes the already-paid period.
94
+
95
+ Monthly spending is not automatically refunded when a VM is stopped, deleted or
96
+ replaced, or renewal is canceled. A support-approved wallet refund reverses the
97
+ original period’s payments and coverage together, through the existing audited
98
+ admin operation queue. The current-period refund also disables renewal. An old
99
+ period refund cannot revoke a newer month; purchased extras are preserved. There
100
+ is no customer SDK refund operation. Cash refunds remain provider verified.
101
+
102
+ Use `previewCapacity` with `billingMode: 'payg'` and `paymentSource: 'wallet'`
103
+ to switch a hosted monthly pool to PAYG. Confirming schedules cancellation of
104
+ the old subscription at its paid-through date. The PAYG period starts only
105
+ after Stripe confirms the old subscription has ended. Cancel the pending
106
+ switch with `cancelCapacityChange` before the boundary to restore renewal.
107
+ An active wallet period keeps wallet payment for pool or mode changes; fund
108
+ that wallet by card if needed.
109
+
110
+ `billing.capacity(namespace).pendingCheckout` exposes the existing checkout URL
111
+ and quote ID after a lost response or reload. Resume that URL or cancel with
112
+ `cancelCapacityChange`; do not open a competing checkout.
113
+
114
+ At expiry compute stops, and the initial tariff retains disks for at least
115
+ 30 days without automatic deletion. Provisioned storage is charged until
116
+ deleted. `capacity.retention.amountDue` and `storagePerGiBMonth` are USD dollars;
117
+ `quote.retainedStorageAmountDue` is USD cents, separate from compute pricing.
118
+ Fund the wallet to settle storage arrears before restarting. A confirmed late
119
+ renewal reverses storage charges for any time it covers.
120
+
121
+ Managed proxy transfer is optional in both modes, charged only when using
122
+ Oblien's managed internet proxy. Public routes and a customer-supplied proxy
123
+ do not use this paid allowance. Quote a transfer pack with
124
+ `previewNetworkTopup(namespace, { unitAmount, idempotencyKey })`, then redeem it
125
+ through `confirmCapacity`. The pack uses eligible wallet funds and grants the
126
+ returned `networkBytes`; unused bytes carry forward. Compute remains covered
127
+ when its paid period is active even if the transfer allowance runs out.
128
+
129
+ `capacity.savings.monthlyDifference` includes the prepaid fee and may be negative
130
+ for an idle pool. `billing.savings({ namespace, month: '2026-10' })` returns a
131
+ ledger comparison for a UTC month; `monthlyCoveredUsage` excludes subscription
132
+ fees and is not cash savings. Respect `complete: false` for incomplete historical
133
+ breakdowns. Do not manufacture dollar conversions or savings locally.
134
+
135
+ Owner-only billing events include `capacity.changed`, `capacity.renewed`,
136
+ `capacity.expired`, `capacity.payment_required`, `capacity.revoked`,
137
+ `network.topup_applied`, `network.allowance.low`, `network.allowance.depleted`,
138
+ `storage.retention.payment_required` and `storage.retention.paid`.
139
+ They use the same signature, event-ID deduplication and namespace checks as the
140
+ existing subscription events. Keep all billing credentials on the server.
141
+
142
+ Personal recurring compute uses the same management methods: `subscription()`, `cancelSubscription()`, `resumeSubscription()` and `portal()` omit the namespace; plan-change mutations take `null`. Reseller calls must always pass the namespace derived from the authenticated customer. Billing events use `namespace: null` for personal scope.
143
+
144
+ Full terms and routes: https://oblien.com/docs/concepts/compute-billing.
145
+
146
+ ## Existing metered subscriptions
2
147
 
3
148
  Namespace management is available from `oblien@2.3.0`; reseller checkout and
4
149
  status reads from `2.4.0`. The `2.5.0` source adds typed offer policy/resource
@@ -17,7 +162,7 @@ Do not reassign a customer's namespace slug to someone else: its billing history
17
162
  stays attached to that owner/namespace identity.
18
163
 
19
164
  Omit `namespace` when creating a personal workspace. Its response has
20
- `namespace: null`, and billing uses the owner's account wallet and account plan.
165
+ `namespace: null`. A personal capacity contract, when purchased, supplies its compute terms and resource pool. Without one, the existing account wallet and account plan apply. Personal capacity does not replace the account-tier subscription or alter any named namespace subscription.
21
166
  Namespace defaults do not apply to personal workspaces. A namespace literally named
22
167
  `default` or `null` is a separate customer budget. An enabled namespace policy,
23
168
  including an unlimited one, governs that namespace independently of the owner's
@@ -67,7 +212,7 @@ an unapproved host returns `billing_redirect_not_allowed`. Supplied URLs require
67
212
  to the first namespace checkout, without copying the API-key owner's details.
68
213
  Reuse an idempotency key only when retrying the identical request.
69
214
 
70
- Paid subscriptions provision the namespace and set its quota. Renewals reset usage
215
+ Paid metered subscriptions provision the namespace and set its quota. Renewals reset usage
71
216
  once per cycle; purchased top-ups increase the ceiling and carry only their unused remainder into renewal.
72
217
  Top-ups, renewals, and funded policy changes clear suspensions caused by billing;
73
218
  manual suspensions stay in place. Workspaces can then be started explicitly.
@@ -131,7 +276,9 @@ is uncapped. `overdraft` must not exceed `suspendThreshold` when both are set.
131
276
 
132
277
  ## Access and reconciliation
133
278
 
134
- `entitlement()` returns `active`, `past_due`, `credit_exhausted`, or `canceled`.
279
+ `entitlement()` preserves `active`, `past_due`, `credit_exhausted`, and `canceled` across both contracts. Capacity responses include `tierId: 'capacity'`, `billingMode`, `computeCovered` and `capacity`. Their compatibility quota has null limit/balance and no alert. Read the returned `balance().blocking`, coverage and resource pool; do not infer an unlimited physical pool or a finite compute allowance from that quota. Monthly coverage survives an empty owner wallet, while manual suspension and resource admission remain enforced.
280
+
281
+ The following allowance/tier behavior applies to existing metered subscriptions.
135
282
 
136
283
  The paid tier and period belong to that namespace's subscription. An account or
137
284
  sibling namespace subscription cannot supply them. A namespace that has never
@@ -156,6 +303,8 @@ Billing events use a durable outbox with retry. Reconcile with `entitlement()` a
156
303
 
157
304
  `POST /billing/checkout` also accepts a server-defined `offer` instead of a catalog `planTierId` or `packId`. Keep this request behind your authenticated backend and resolve the customer's namespace from your own database.
158
305
 
306
+ Choose the offer type explicitly. The example below is a **metered credit offer**. Monthly capacity uses `billingMode: 'monthly'`, `capacity: { vcpus, memoryMb, diskGb, workspaces }`, `credits: 0`, and no `policy`. It requires a monthly subscription, a retail price covering the saved provider cost, and successful physical admission. See [the monthly reseller example](https://oblien.com/docs/saas-reselling#monthly-capacity-offer).
307
+
159
308
  ```json
160
309
  {
161
310
  "namespace": "tenant-a",
@@ -188,9 +337,12 @@ This charges **$10**, funds the **owner's Oblien wallet** at the standard rate (
188
337
  | `offer.description` | Optional customer-facing text, at most 500 characters |
189
338
  | `offer.unitAmount` | Required integer USD cents, 100–1,000,000 ($1–$10,000) |
190
339
  | `offer.currency` | `usd` only; defaults to `usd` |
191
- | `offer.credits` | Required integer namespace allowance, 1–1,000,000,000; independent of wallet funding |
192
- | `offer.policy` | Subscription only: optional `overdraft`, `suspendThreshold`, `onOverdraftAction`; defaults to zero grace and `stop_workspaces` |
193
- | `offer.resourceLimits` | Subscription only: nonempty subset of `max_workspaces`, `max_vcpus`, `max_ram_mb`, `max_disk_gb`; values are integers 0–1,000,000,000 or `null` |
340
+ | `offer.billingMode` | `monthly` purchases capacity; omit for a metered allowance. The historical `payg` offer value also selects that allowance product; new capped PAYG uses `previewCapacity`. |
341
+ | `offer.capacity` | Monthly only: required shared `vcpus`, `memoryMb`, `diskGb`, `workspaces`. |
342
+ | `offer.tariffId` | Monthly only: optional published tariff ID; saved terms are preserved by default. |
343
+ | `offer.credits` | Metered: integer 1–1,000,000,000. Monthly: `0` (the API also defaults an omitted value to zero). |
344
+ | `offer.policy` | Metered subscription only: optional `overdraft`, `suspendThreshold`, `onOverdraftAction`. Rejected for monthly capacity. |
345
+ | `offer.resourceLimits` | Subscription only: nonempty subset of `max_workspaces`, `max_vcpus`, `max_ram_mb`, `max_disk_gb`, `max_total_vcpus`, `max_total_ram_mb`, `max_total_disk_gb`; integer values 0–1,000,000,000 or `null`. These can further restrict a paid pool. |
194
346
  | `metadata` | Optional, only with `offer`: at most 35 string entries; key `[A-Za-z0-9_]`, length 1–40; value at most 500 characters without control characters |
195
347
  | `idempotencyKey` | Required with `offer`, nonempty string up to 200 characters; reuse only for an identical request |
196
348
 
@@ -206,7 +358,7 @@ Check `billing.catalog().reseller` before enabling offers with policy or limits:
206
358
  capability. SDK 2.4.0 already transports reseller offers; the 2.5.0 source adds
207
359
  these TypeScript fields and public reseller type exports.
208
360
 
209
- Grace is zero by default. To permit 60 extra namespace credits, save
361
+ For metered offers, grace is zero by default. To permit 60 extra namespace credits, save
210
362
  `policy: { overdraft: 60, suspendThreshold: 60, onOverdraftAction: 'stop_workspaces' }`
211
363
  on the subscription offer. `suspendThreshold` must be at least `overdraft`.
212
364
  `quota.balance` already includes grace (`limit + overdraft - used`); never add it
@@ -222,7 +374,7 @@ refund of the current cycle removes its remaining allowance and grace; an old
222
374
  invoice refund cannot erase a newer cycle.
223
375
 
224
376
  `max_workspaces` counts allocated workspaces in this namespace. CPU, RAM and disk
225
- are per-workspace caps. Oblien resolves the strictest cap from the saved offer,
377
+ are per-workspace caps. The three `max_total_*` fields additionally bound combined allocated resources, including stopped workspaces and pending changes. Oblien resolves the strictest cap from the saved offer,
226
378
  configured namespace policy, owner account and platform. `null` inherits capacity;
227
379
  it never removes another layer's restriction. Clients submit policy directly
228
380
  without fetching account quota or calculating capacity. Namespace detail and
@@ -282,6 +434,8 @@ Requires an `admin` or `billing` credential. Looks up both owner and namespace b
282
434
 
283
435
  `fulfilled` means initial processing finished; always inspect the net credit fields and `fulfillmentStatus` for `partially_refunded`, `refunded` or `disputed`. Use `GET /billing/entitlement` and `/billing/balance` for current access. The lookup describes the checkout's initial payment, not its later renewal invoices. Reseller subscriptions also expose `offer` and `metadata` through `GET /billing/subscription`; their `tierId` is `reseller` and does not upgrade owner capacity.
284
436
 
437
+ Monthly checkout results expose gross `walletCreditsFunded`, `capacityCreditsCharged` and signed `walletCreditDelta`, with zero `namespaceCreditsGranted`. Gross funding is not the spendable remainder; read committed capacity coverage instead of granting credits again.
438
+
285
439
  Custom `payment.succeeded`, `subscription.renewed` and `entitlement.changed` events include `orgRef`, `namespace`, `kind`, `checkoutId`, `paymentId`, saved `offer`, application `metadata`, `amount: { unitAmount, currency }`, net `walletCredits` and `namespaceCredits`. Fulfillment uses stable receipt-based event IDs. Verify the raw-body HMAC, deduplicate by event ID, then re-read entitlement to handle reordering. Financial billing events are committed to a durable outbox with retries. Keep reconciliation polling to handle delayed or exhausted delivery and event reordering.
286
440
 
287
441
  ### Useful checkout and portal errors
@@ -385,9 +539,10 @@ Errors use `{ success:false, code, message, requestId }`, with safe diagnostic d
385
539
 
386
540
  ## Reseller subscription plan changes
387
541
 
542
+ The same methods also change hosted monthly capacity. Monthly offers use zero compute credits and no credit policy. The provider reserves the new pool and applies an immediate upgrade only after confirmed funding. Resource reductions and billing-mode changes wait for renewal, even when retail price increases. The quote's direction and effective date are authoritative. The prorated credit-increase formula below applies to metered offers. Direct owner capacity subscriptions use these methods without requiring reseller Enterprise eligibility.
543
+
388
544
 
389
- These endpoints change an **existing reseller offer**, without creating a second
390
- subscription or changing the owner's account plan. New quotes and acceptance require
545
+ These endpoints change an **existing reseller offer** or a direct personal monthly capacity subscription, without creating a second subscription or changing the owner's account-tier plan. For direct personal capacity, omit `namespace` (or send `null`) and use backend-priced capacity terms; reseller eligibility is not required for that saved direct purchase. The namespace inputs in the reseller examples below are mandatory for customer isolation. New reseller quotes and acceptance require
391
546
  an Enterprise owner and a server API key with `billing` or `admin` scope. Read and
392
547
  cancel operations remain available if reseller eligibility later ends. End-user
393
548
  namespace/workspace tokens cannot call billing APIs. Your backend must derive the
package/docs/desktop.md CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  Desktop is an image capability. Linux virtual-display providers support named,
4
4
  saved desktops with independent applications, profiles and resolutions. The
5
- current macOS provider exposes one console (`can_create: false`). Discover the
5
+ current macOS provider exposes one console connection, which can be renamed,
6
+ deleted and added again. Discover the
6
7
  capabilities rather than branching on image names.
7
8
 
8
9
  ```ts
@@ -37,15 +38,19 @@ routing remains on the image gateway, independent of `runtime.forTarget()`.
37
38
 
38
39
  The default limit is 10 saved desktops, including stopped ones. Each running
39
40
  desktop uses the workspace's CPU/RAM; software packages remain shared read-only.
40
- Resolution is required at creation, between 640×480 and 3840×2160. Change a stopped
41
- desktop's screen size with `updateSession(id, { resolution: { width, height } })`.
42
- Names can change while running. Reuse the same `idempotency_key` and request body
41
+ Resolution is required for virtual desktops at creation, between 640×480 and
42
+ 3840×2160. Change a running or stopped Linux desktop's screen size with `updateSession(id, { resolution: { width, height } })`.
43
+ Live resizing keeps applications open. Check `session.can_resize`; OS consoles
44
+ without this capability use their native display settings. Names can change while running. Reuse the same `idempotency_key` and request body
43
45
  on creation retries. Responses contain `{success: true, session}`; poll while
44
- `state` is `starting` or `stopping`. Other states: `running`, `stopped`, `failed`.
46
+ `state` is `starting`, `stopping` or `deleting`. Other states: `running`, `stopped`, `failed`.
45
47
 
46
48
  Disconnecting preserves running applications. **Stop** ends that desktop's apps
47
- and keeps its profile. **Start** opens it again. **Delete** requires a stopped
48
- desktop and removes its profile, including files saved there. Other desktops and
49
+ and keeps its profile. **Start** opens it again. **Delete** automatically stops a running virtual desktop and removes its profile,
50
+ including files saved there. It returns once deletion is accepted; poll the
51
+ session list until it disappears. A main OS console has no private profile: Delete
52
+ removes its saved connection and disconnects viewers, preserving OS apps and files.
53
+ Add it again with `createSession({name: "Main desktop"})`, omitting resolution. Other desktops and
49
54
  shared workspace files remain. A workspace cold boot restarts previously running
50
55
  desktops with their profiles; it does not restore open app RAM. Use the existing
51
56
  supported Linux VM memory snapshot/restore for that.
@@ -87,6 +92,7 @@ oblien desktop create WORKSPACE_ID --name Development --resolution 1920x1080
87
92
  oblien desktop enable WORKSPACE_ID
88
93
  oblien desktop vnc WORKSPACE_ID --session DESKTOP_ID --port 5901
89
94
  oblien desktop ssh WORKSPACE_ID --session DESKTOP_ID
95
+ oblien desktop update WORKSPACE_ID DESKTOP_ID --resolution 1600x900
90
96
  oblien desktop stop WORKSPACE_ID DESKTOP_ID
91
97
  oblien desktop start WORKSPACE_ID DESKTOP_ID
92
98
  oblien desktop delete WORKSPACE_ID DESKTOP_ID
@@ -2,6 +2,8 @@
2
2
 
3
3
  Group workspaces into isolated namespaces with **resource limits**, **spending quotas**, lifecycle controls, and **per-namespace usage** — the building block for multi-tenant setups (one namespace per customer/team).
4
4
 
5
+ Account credit subscriptions fund the existing wallet and set the owner resource tier. That wallet funds a [capped PAYG or prepaid monthly contract](./billing.md#payg-and-prepaid-monthly-capacity). A paid monthly pool has no second finite compute-credit allowance. Existing credit contracts retain their quota rules; resource policy edits alone do not purchase or migrate coverage. Omitting a workspace namespace creates a personal account workspace with `namespace: null`; the literal `default` is a separate named namespace.
6
+
5
7
  ```typescript
6
8
  const ns = client.namespaces;
7
9
  ```
@@ -20,7 +22,7 @@ const { data } = await ns.create({
20
22
  name: 'production',
21
23
  resource_limits: {
22
24
  max_workspaces: 50,
23
- max_vcpus: 16, // per-workspace cap
25
+ max_vcpus: 12, // per-workspace platform maximum
24
26
  max_ram_mb: 32768,
25
27
  max_disk_gb: 100,
26
28
  },
@@ -38,8 +40,9 @@ Invalid numbers and unknown keys return `invalid_resource_limits`.
38
40
  `create`, `ensure`, `get` and `update` expose both `data.resource_limits` (saved
39
41
  policy) and `data.effective_resource_limits` (current enforced ceilings). The
40
42
  latter can change with account capacity while saved customer terms stay intact.
41
- These limits do not reserve host capacity or funds. Account pool usage and
42
- credits are checked independently at allocation time.
43
+ These policy limits do not reserve host capacity or funds. Account capacity and
44
+ the namespace's applicable billing contract are checked at allocation time.
45
+ Monthly coverage comes from the separate verified capacity purchase.
43
46
 
44
47
  ## Lifecycle
45
48
 
@@ -52,16 +55,17 @@ const { namespaces } = await ns.list();
52
55
 
53
56
  ## Quotas (optional)
54
57
 
55
- Spending limits per service, with overdraft + threshold webhooks. Skip these if you bill externally (use **usage units** below instead).
58
+ Spending limits for credit-metered services, with overdraft and threshold webhooks. This Mode A example applies when your backend owns a metered allowance cycle. Hosted subscriptions reconcile their own paid cycles. Monthly compute uses paid capacity coverage instead of these finite compute quotas.
56
59
 
57
60
  ```typescript
58
61
  await ns.setQuota({
59
- namespace: 'production', service: 'sandbox',
62
+ namespace: 'production', service: 'workspace_vm',
60
63
  quotaLimit: 500, overdraft: 50,
61
64
  onOverdraftAction: 'stop_workspaces',
62
65
  notificationThresholds: [80, 95], // fires namespace.quota.threshold webhooks
63
66
  });
64
- await ns.resetQuota({ namespace: 'production', service: 'sandbox' });
67
+ // After external payment, reuse the same cycle end on retry.
68
+ await client.billing.resetQuota('production', { periodEnd: '2026-11-01T00:00:00Z' });
65
69
  await ns.listWithQuotas();
66
70
  ```
67
71
 
@@ -90,6 +94,8 @@ A namespace-scoped key is pinned to its namespace: list/get/usage/webhooks all a
90
94
 
91
95
  ## Namespace credit alerts and customer recovery
92
96
 
97
+ Use these alerts for metered allowances. For monthly capacity, read coverage, transfer and retained-storage state with `billing.capacity(namespace)` and the [capacity events](./billing.md#payg-and-prepaid-monthly-capacity). A transfer warning alone does not revoke paid compute.
98
+
93
99
  Oblien computes the warning state from the same quota row that enforces spending.
94
100
  Read `quota.alert` from `GET /billing/entitlement?namespace=...`, or `alert` from
95
101
  `GET /billing/balance?namespace=...`. Namespace quota rows also include `alert`.
@@ -0,0 +1,19 @@
1
+ # SDK 2.8.0
2
+
3
+ Adds typed capped PAYG and prepaid monthly capacity APIs, wallet redemption,
4
+ Stripe checkout, renewal preferences, pending checkout recovery, capacity
5
+ changes and managed proxy transfer packs. Both compute modes use the backend's
6
+ saved tariff, namespace contract and existing billing events.
7
+
8
+ Responses distinguish paid compute coverage, retained-storage balances,
9
+ resource limits, purchased transfer and recorded cap savings. Quote amounts
10
+ are cents; savings and retention balances are dollars. Storage and transfer
11
+ events use the existing signed webhook contract.
12
+
13
+ Requires the matching capacity API and compatible VM nodes. Read
14
+ `billing.capacityCatalog()` before enabling sales, and use saved idempotency
15
+ keys for every confirmation. Existing namespace, workspace and reseller
16
+ methods remain compatible. See [billing](../billing.md) for the full flow.
17
+
18
+ This release is prepared for the repository owner to publish. It has not been
19
+ published automatically.
@@ -0,0 +1,29 @@
1
+ # SDK 2.8.1
2
+
3
+ Makes namespace selection optional for direct compute purchases and management.
4
+ `billing.capacity()` and `billing.subscription()` default to personal workspaces;
5
+ capacity quote, checkout and change methods accept `null` as the namespace.
6
+ `billing.portal()` also opens personal compute billing without an argument.
7
+
8
+ Personal responses return `namespace: null`. The SDK omits the namespace from
9
+ requests instead of sending the literal string `null`. Named namespaces,
10
+ including a namespace named `default`, remain separate. Reseller checkout still
11
+ requires an explicit customer namespace and the existing reseller permissions.
12
+ Personal compute subscriptions do not replace account tiers or customer plans.
13
+
14
+ The catalog types also expose optional backend-computed PAYG hourly/storage
15
+ examples and wallet deposit limits, in USD cents. Monthly and PAYG both use a
16
+ shared resource pool: creating or replacing a VM does not start a subscription.
17
+ Wallet deposits fund usage; they do not increase the pool's resource limits.
18
+
19
+ The response types also expose backend-derived `accountPlan`, wallet balances in
20
+ USD, sizing-example `available` flags, and `allocationBasis` / `runningPool`.
21
+ Account credit subscriptions remain the funding product. Monthly pools spend
22
+ eligible paid wallet funds upfront; PAYG spends measured usage. There is one
23
+ wallet and ledger. Existing direct-card contracts retain their saved terms.
24
+
25
+ The matching API and dashboard are deployed. Existing namespace calls remain
26
+ compatible. See [billing](../billing.md) for the complete flow.
27
+
28
+ This patch is ready for the repository owner to publish; it has not been
29
+ published automatically. Version 2.8.0 is already available on npm.
package/docs/webhooks.md CHANGED
@@ -14,6 +14,8 @@ const { events } = await wh.events();
14
14
 
15
15
  Includes: `vm.stopped`, `vm.archived`, `workload.started|exited|failed|stopped|restart_loop`, `credits.usage`, `credits.low`, `credits.depleted`, `namespace.quota.threshold`.
16
16
 
17
+ Compute billing also publishes `capacity.changed`, `capacity.renewed`, `capacity.expired`, `capacity.payment_required`, `capacity.revoked`, `network.topup_applied`, `network.allowance.low`, `network.allowance.depleted`, `storage.retention.payment_required` and `storage.retention.paid`. These use durable signed billing delivery. Reconcile current coverage, transfer and storage with `billing.capacity(namespace)` after deduplicating the event ID.
18
+
17
19
  ## Create (namespace-scoped or account-wide)
18
20
 
19
21
  ```typescript
@@ -25,7 +27,7 @@ const { webhook } = await wh.create({
25
27
  });
26
28
  ```
27
29
 
28
- A namespace-bound webhook receives only events that carry that namespace; account-wide webhooks receive everything. Namespace-scoped API keys are auto-pinned to their namespace.
30
+ A namespace-bound webhook receives only events that carry that namespace; account-wide webhooks receive their owner's authorized events. Register billing, credit, capacity, transfer and retained-storage hooks with an owner `admin` credential. Namespace-scoped keys can manage authorized operational hooks in their own namespace, but cannot manage billing webhook configurations.
29
31
 
30
32
  ## Manage
31
33
 
@@ -44,6 +46,8 @@ await wh.delete(webhook.id);
44
46
 
45
47
  ## Namespace credit alerts and customer recovery
46
48
 
49
+ These describe metered allowances. Monthly capacity has no additional compute-credit budget to exhaust; use the capacity, transfer and retained-storage events above. Read the API's `blocking` value rather than deriving access from a numeric credit balance.
50
+
47
51
  Oblien computes the warning state from the same quota row that enforces spending.
48
52
  Read `quota.alert` from `GET /billing/entitlement?namespace=...`, or `alert` from
49
53
  `GET /billing/balance?namespace=...`. Namespace quota rows also include `alert`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oblien",
3
- "version": "2.7.1",
3
+ "version": "2.8.1",
4
4
  "description": "Official TypeScript SDK for the Oblien Workspace API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",