oblien 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/billing.d.ts +47 -8
- package/dist/billing.d.ts.map +1 -1
- package/dist/billing.js +54 -7
- package/dist/billing.js.map +1 -1
- package/dist/cli/commands/desktop.d.ts.map +1 -1
- package/dist/cli/commands/desktop.js +35 -4
- package/dist/cli/commands/desktop.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/resources/desktop.d.ts +14 -1
- package/dist/resources/desktop.d.ts.map +1 -1
- package/dist/resources/desktop.js +12 -2
- package/dist/resources/desktop.js.map +1 -1
- package/dist/runtime/desktop-tunnel.d.ts +1 -0
- package/dist/runtime/desktop-tunnel.d.ts.map +1 -1
- package/dist/runtime/desktop-tunnel.js +2 -1
- package/dist/runtime/desktop-tunnel.js.map +1 -1
- package/dist/runtime/desktop.d.ts +18 -2
- package/dist/runtime/desktop.d.ts.map +1 -1
- package/dist/runtime/desktop.js +24 -5
- package/dist/runtime/desktop.js.map +1 -1
- package/dist/runtime.d.ts +1 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/types/billing.d.ts +256 -13
- package/dist/types/billing.d.ts.map +1 -1
- package/dist/types/desktop.d.ts +51 -0
- package/dist/types/desktop.d.ts.map +1 -0
- package/dist/types/desktop.js +6 -0
- package/dist/types/desktop.js.map +1 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/webhooks.d.ts +1 -1
- package/dist/types/webhooks.d.ts.map +1 -1
- package/docs/billing.md +110 -8
- package/docs/desktop.md +82 -93
- package/docs/namespaces.md +12 -6
- package/docs/releases/2.8.0.md +19 -0
- package/docs/webhooks.md +5 -1
- package/package.json +1 -1
package/docs/billing.md
CHANGED
|
@@ -1,5 +1,96 @@
|
|
|
1
1
|
# Namespace billing
|
|
2
2
|
|
|
3
|
+
## PAYG and prepaid monthly capacity
|
|
4
|
+
|
|
5
|
+
Compute has two modes, `payg` and `monthly`. Stripe and wallet funds are payment
|
|
6
|
+
sources. Both modes share the namespace contract, resource enforcement, usage
|
|
7
|
+
ledger and signed billing events. Direct capacity purchases are available to
|
|
8
|
+
the account owner; hosting a customer checkout through reseller `offer` still
|
|
9
|
+
requires an Enterprise owner.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
const catalog = await client.billing.capacityCatalog();
|
|
13
|
+
const selected = catalog.presets.find(p => p.id === 'small')!;
|
|
14
|
+
const { quote } = await client.billing.previewCapacity(namespace, {
|
|
15
|
+
capacity: selected.capacity,
|
|
16
|
+
billingMode: 'monthly', paymentSource: 'wallet', autoRenew: false,
|
|
17
|
+
idempotencyKey: savedOrder.previewKey,
|
|
18
|
+
});
|
|
19
|
+
// Review backend-calculated amounts and effectiveAt before confirming.
|
|
20
|
+
await client.billing.confirmCapacity(namespace, {
|
|
21
|
+
quoteId: quote.id, idempotencyKey: savedOrder.confirmKey,
|
|
22
|
+
});
|
|
23
|
+
const { capacity, catalog: savedPrices } = await client.billing.capacity(namespace);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Existing subscriptions retain their saved model after an SDK upgrade. Read `capacity(namespace)` first; a null capacity means this namespace 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.
|
|
27
|
+
|
|
28
|
+
For PAYG use `billingMode: 'payg'` and `paymentSource: 'wallet'`. For recurring
|
|
29
|
+
card payment use `paymentSource: 'stripe'` and confirm the saved quote with
|
|
30
|
+
`capacityCheckout` instead. Native Stripe Checkout is the default, with the
|
|
31
|
+
existing optional `allowPromotionCodes` and `checkoutMode` controls. Returning
|
|
32
|
+
from checkout never proves payment: inspect committed coverage and signed events.
|
|
33
|
+
|
|
34
|
+
Quotes use USD **cents**; savings use USD **dollars**. Rates and presets come from
|
|
35
|
+
the backend, and existing contracts return their saved-tariff catalog. Only
|
|
36
|
+
eligible verified paid wallet funds can buy monthly coverage. Namespace
|
|
37
|
+
allowances and promotional grants are not money. Read `computeCovered` and
|
|
38
|
+
`periodEnd`: a prepaid month has no additional compute-credit ceiling, and a
|
|
39
|
+
zero wallet cannot remove that paid compute coverage. The manual namespace
|
|
40
|
+
suspension and purchased resource pool still apply.
|
|
41
|
+
|
|
42
|
+
Wallet monthly renewal is opt-in through
|
|
43
|
+
`setCapacityAutoRenew(namespace, { autoRenew, idempotencyKey })`. Wallet changes
|
|
44
|
+
use the same preview and confirm methods; pending reductions can be canceled
|
|
45
|
+
with `cancelCapacityChange(namespace, { quoteId, idempotencyKey })`. Hosted
|
|
46
|
+
subscription changes use `previewPlanChange` / `changePlan`, and renewal uses
|
|
47
|
+
`cancelSubscription` / `resumeSubscription`. Do not start a competing checkout
|
|
48
|
+
for an existing live subscription. Upgrades charge the prorated difference and
|
|
49
|
+
preserve usage/top-ups; reductions wait for the next period. Failed payment
|
|
50
|
+
retains the prior plan.
|
|
51
|
+
|
|
52
|
+
Use `previewCapacity` with `billingMode: 'payg'` and `paymentSource: 'wallet'`
|
|
53
|
+
to switch a hosted monthly pool to PAYG. Confirming schedules cancellation of
|
|
54
|
+
the old subscription at its paid-through date. The PAYG period starts only
|
|
55
|
+
after Stripe confirms the old subscription has ended. Cancel the pending
|
|
56
|
+
switch with `cancelCapacityChange` before the boundary to restore renewal.
|
|
57
|
+
An active wallet period keeps wallet payment for pool or mode changes; fund
|
|
58
|
+
that wallet by card if needed.
|
|
59
|
+
|
|
60
|
+
`billing.capacity(namespace).pendingCheckout` exposes the existing checkout URL
|
|
61
|
+
and quote ID after a lost response or reload. Resume that URL or cancel with
|
|
62
|
+
`cancelCapacityChange`; do not open a competing checkout.
|
|
63
|
+
|
|
64
|
+
At expiry compute stops, and the initial tariff retains disks for at least
|
|
65
|
+
30 days without automatic deletion. Provisioned storage is charged until
|
|
66
|
+
deleted. `capacity.retention.amountDue` and `storagePerGiBMonth` are USD dollars;
|
|
67
|
+
`quote.retainedStorageAmountDue` is USD cents, separate from compute pricing.
|
|
68
|
+
Fund the wallet to settle storage arrears before restarting. A confirmed late
|
|
69
|
+
renewal reverses storage charges for any time it covers.
|
|
70
|
+
|
|
71
|
+
Managed proxy transfer is separate in both modes. Quote a transfer pack with
|
|
72
|
+
`previewNetworkTopup(namespace, { unitAmount, idempotencyKey })`, then redeem it
|
|
73
|
+
through `confirmCapacity`. The pack uses eligible wallet funds and grants the
|
|
74
|
+
returned `networkBytes`; unused bytes carry forward. Compute remains covered
|
|
75
|
+
when its paid period is active even if the transfer allowance runs out.
|
|
76
|
+
|
|
77
|
+
`capacity.savings.monthlyDifference` includes the prepaid fee and may be negative
|
|
78
|
+
for an idle pool. `billing.savings({ namespace, month: '2026-10' })` returns a
|
|
79
|
+
ledger comparison for a UTC month; `monthlyCoveredUsage` excludes subscription
|
|
80
|
+
fees and is not cash savings. Respect `complete: false` for incomplete historical
|
|
81
|
+
breakdowns. Do not manufacture dollar conversions or savings locally.
|
|
82
|
+
|
|
83
|
+
Owner-only billing events include `capacity.changed`, `capacity.renewed`,
|
|
84
|
+
`capacity.expired`, `capacity.payment_required`, `capacity.revoked`,
|
|
85
|
+
`network.topup_applied`, `network.allowance.low`, `network.allowance.depleted`,
|
|
86
|
+
`storage.retention.payment_required` and `storage.retention.paid`.
|
|
87
|
+
They use the same signature, event-ID deduplication and namespace checks as the
|
|
88
|
+
existing subscription events. Keep all billing credentials on the server.
|
|
89
|
+
|
|
90
|
+
Full terms and routes: https://oblien.com/docs/concepts/compute-billing.
|
|
91
|
+
|
|
92
|
+
## Existing metered subscriptions
|
|
93
|
+
|
|
3
94
|
Namespace management is available from `oblien@2.3.0`; reseller checkout and
|
|
4
95
|
status reads from `2.4.0`. The `2.5.0` source adds typed offer policy/resource
|
|
5
96
|
caps and exported reseller types, with the matching API deployment.
|
|
@@ -67,7 +158,7 @@ an unapproved host returns `billing_redirect_not_allowed`. Supplied URLs require
|
|
|
67
158
|
to the first namespace checkout, without copying the API-key owner's details.
|
|
68
159
|
Reuse an idempotency key only when retrying the identical request.
|
|
69
160
|
|
|
70
|
-
Paid subscriptions provision the namespace and set its quota. Renewals reset usage
|
|
161
|
+
Paid metered subscriptions provision the namespace and set its quota. Renewals reset usage
|
|
71
162
|
once per cycle; purchased top-ups increase the ceiling and carry only their unused remainder into renewal.
|
|
72
163
|
Top-ups, renewals, and funded policy changes clear suspensions caused by billing;
|
|
73
164
|
manual suspensions stay in place. Workspaces can then be started explicitly.
|
|
@@ -131,7 +222,9 @@ is uncapped. `overdraft` must not exceed `suspendThreshold` when both are set.
|
|
|
131
222
|
|
|
132
223
|
## Access and reconciliation
|
|
133
224
|
|
|
134
|
-
`entitlement()`
|
|
225
|
+
`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.
|
|
226
|
+
|
|
227
|
+
The following allowance/tier behavior applies to existing metered subscriptions.
|
|
135
228
|
|
|
136
229
|
The paid tier and period belong to that namespace's subscription. An account or
|
|
137
230
|
sibling namespace subscription cannot supply them. A namespace that has never
|
|
@@ -156,6 +249,8 @@ Billing events use a durable outbox with retry. Reconcile with `entitlement()` a
|
|
|
156
249
|
|
|
157
250
|
`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
251
|
|
|
252
|
+
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).
|
|
253
|
+
|
|
159
254
|
```json
|
|
160
255
|
{
|
|
161
256
|
"namespace": "tenant-a",
|
|
@@ -188,9 +283,12 @@ This charges **$10**, funds the **owner's Oblien wallet** at the standard rate (
|
|
|
188
283
|
| `offer.description` | Optional customer-facing text, at most 500 characters |
|
|
189
284
|
| `offer.unitAmount` | Required integer USD cents, 100–1,000,000 ($1–$10,000) |
|
|
190
285
|
| `offer.currency` | `usd` only; defaults to `usd` |
|
|
191
|
-
| `offer.
|
|
192
|
-
| `offer.
|
|
193
|
-
| `offer.
|
|
286
|
+
| `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`. |
|
|
287
|
+
| `offer.capacity` | Monthly only: required shared `vcpus`, `memoryMb`, `diskGb`, `workspaces`. |
|
|
288
|
+
| `offer.tariffId` | Monthly only: optional published tariff ID; saved terms are preserved by default. |
|
|
289
|
+
| `offer.credits` | Metered: integer 1–1,000,000,000. Monthly: `0` (the API also defaults an omitted value to zero). |
|
|
290
|
+
| `offer.policy` | Metered subscription only: optional `overdraft`, `suspendThreshold`, `onOverdraftAction`. Rejected for monthly capacity. |
|
|
291
|
+
| `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
292
|
| `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
293
|
| `idempotencyKey` | Required with `offer`, nonempty string up to 200 characters; reuse only for an identical request |
|
|
196
294
|
|
|
@@ -206,7 +304,7 @@ Check `billing.catalog().reseller` before enabling offers with policy or limits:
|
|
|
206
304
|
capability. SDK 2.4.0 already transports reseller offers; the 2.5.0 source adds
|
|
207
305
|
these TypeScript fields and public reseller type exports.
|
|
208
306
|
|
|
209
|
-
|
|
307
|
+
For metered offers, grace is zero by default. To permit 60 extra namespace credits, save
|
|
210
308
|
`policy: { overdraft: 60, suspendThreshold: 60, onOverdraftAction: 'stop_workspaces' }`
|
|
211
309
|
on the subscription offer. `suspendThreshold` must be at least `overdraft`.
|
|
212
310
|
`quota.balance` already includes grace (`limit + overdraft - used`); never add it
|
|
@@ -222,7 +320,7 @@ refund of the current cycle removes its remaining allowance and grace; an old
|
|
|
222
320
|
invoice refund cannot erase a newer cycle.
|
|
223
321
|
|
|
224
322
|
`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,
|
|
323
|
+
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
324
|
configured namespace policy, owner account and platform. `null` inherits capacity;
|
|
227
325
|
it never removes another layer's restriction. Clients submit policy directly
|
|
228
326
|
without fetching account quota or calculating capacity. Namespace detail and
|
|
@@ -282,6 +380,8 @@ Requires an `admin` or `billing` credential. Looks up both owner and namespace b
|
|
|
282
380
|
|
|
283
381
|
`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
382
|
|
|
383
|
+
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.
|
|
384
|
+
|
|
285
385
|
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
386
|
|
|
287
387
|
### Useful checkout and portal errors
|
|
@@ -385,9 +485,11 @@ Errors use `{ success:false, code, message, requestId }`, with safe diagnostic d
|
|
|
385
485
|
|
|
386
486
|
## Reseller subscription plan changes
|
|
387
487
|
|
|
488
|
+
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.
|
|
489
|
+
|
|
388
490
|
|
|
389
491
|
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
|
|
492
|
+
subscription or changing the owner's account plan. New reseller quotes and acceptance require
|
|
391
493
|
an Enterprise owner and a server API key with `billing` or `admin` scope. Read and
|
|
392
494
|
cancel operations remain available if reseller eligibility later ends. End-user
|
|
393
495
|
namespace/workspace tokens cannot call billing APIs. Your backend must derive the
|
package/docs/desktop.md
CHANGED
|
@@ -1,115 +1,104 @@
|
|
|
1
|
-
# Remote desktop
|
|
1
|
+
# Remote desktop sessions
|
|
2
2
|
|
|
3
|
-
Desktop is an image capability.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Desktop is an image capability. Linux virtual-display providers support named,
|
|
4
|
+
saved desktops with independent applications, profiles and resolutions. The
|
|
5
|
+
current macOS provider exposes one console connection, which can be renamed,
|
|
6
|
+
deleted and added again. Discover the
|
|
7
|
+
capabilities rather than branching on image names.
|
|
7
8
|
|
|
8
9
|
```ts
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
const vm = client.workspace(workspaceId);
|
|
11
|
+
const installation = await vm.desktop.installation();
|
|
12
|
+
if (installation.choices?.length && !installation.installed) {
|
|
13
|
+
await vm.desktop.install({ desktop: installation.choices[0].id, restart: true });
|
|
14
|
+
// Poll installation() until ready. Adding software can restart the workspace.
|
|
15
|
+
}
|
|
16
|
+
const runtime = await vm.runtime();
|
|
17
|
+
const { sessions, capabilities } = await vm.desktop.listSessions();
|
|
18
|
+
if (capabilities.can_create) {
|
|
19
|
+
const { session } = await vm.desktop.createSession({
|
|
20
|
+
name: 'Development',
|
|
21
|
+
resolution: { width: 1920, height: 1080 },
|
|
22
|
+
idempotency_key: 'development-desktop',
|
|
23
|
+
});
|
|
24
|
+
// Poll vm.desktop.getSession(session.id) until session.available is true.
|
|
11
25
|
await runtime.desktop.enable();
|
|
12
|
-
const
|
|
13
|
-
const tunnel = await runtime.desktop.tunnel({ port: 5901 });
|
|
14
|
-
// Connect a VNC
|
|
15
|
-
await tunnel.close();
|
|
16
|
-
await runtime.desktop.disable();
|
|
26
|
+
const privateViewer = runtime.desktop.url({ sessionId: session.id });
|
|
27
|
+
const tunnel = await runtime.desktop.tunnel({ sessionId: session.id, port: 5901 });
|
|
28
|
+
// Connect a native VNC app to tunnel.url. Node.js only.
|
|
29
|
+
await tunnel.close(); // Leaves desktop applications running.
|
|
17
30
|
}
|
|
18
31
|
```
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
`listSessions`, `createSession`, `getSession`, `updateSession`, `startSession`,
|
|
34
|
+
`stopSession` and `deleteSession` are available on both `vm.desktop` and
|
|
35
|
+
`runtime.desktop`. The first uses the control API with normal workspace audit
|
|
36
|
+
and scope checks; the second calls the authenticated runtime directly. Desktop
|
|
37
|
+
routing remains on the image gateway, independent of `runtime.forTarget()`.
|
|
38
|
+
|
|
39
|
+
The default limit is 10 saved desktops, including stopped ones. Each running
|
|
40
|
+
desktop uses the workspace's CPU/RAM; software packages remain shared read-only.
|
|
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
|
|
45
|
+
on creation retries. Responses contain `{success: true, session}`; poll while
|
|
46
|
+
`state` is `starting`, `stopping` or `deleting`. Other states: `running`, `stopped`, `failed`.
|
|
47
|
+
|
|
48
|
+
Disconnecting preserves running applications. **Stop** ends that desktop's apps
|
|
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
|
|
54
|
+
shared workspace files remain. A workspace cold boot restarts previously running
|
|
55
|
+
desktops with their profiles; it does not restore open app RAM. Use the existing
|
|
56
|
+
supported Linux VM memory snapshot/restore for that.
|
|
57
|
+
|
|
58
|
+
Sessions are not separate security boundaries. Workspace runtime permission
|
|
59
|
+
authorizes all of its desktops and files. Use separate workspaces for tenants.
|
|
60
|
+
Runtime access and desktop access must be enabled to connect. Desktop disable
|
|
61
|
+
closes all display connections, leaving apps, terminals and workloads running.
|
|
62
|
+
Token rotation or runtime disable revokes display streams as well.
|
|
30
63
|
|
|
31
|
-
|
|
32
|
-
from the owned workspace, then add the selected desktop:
|
|
64
|
+
## Native SSH/VNC apps
|
|
33
65
|
|
|
34
66
|
```ts
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
if (installation.choices?.length) {
|
|
38
|
-
await desktop.install({ desktop: installation.choices[0].id, restart: true });
|
|
39
|
-
}
|
|
67
|
+
const connection = await vm.desktop.sshConnection({ session_id: desktopId });
|
|
68
|
+
// Keep connection.ssh.password secret. It is bound to this desktop.
|
|
40
69
|
```
|
|
41
70
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
Use the returned SSH host (`ssh.oblien.com`), username, temporary password and
|
|
72
|
+
host fingerprint in a VNC app with SSH tunneling. Its virtual VNC destination is
|
|
73
|
+
`127.0.0.1:5900`, with no additional VNC authentication. The ticket grants no SSH
|
|
74
|
+
shell, SFTP, arbitrary forwarding or access to another display. Owner tickets
|
|
75
|
+
expire after eight hours; delegated tickets can expire sooner and follow sharing
|
|
76
|
+
revocation. Consult `expires_at`. Stop/deletion closes that session's streams.
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
are no per-workspace downloads, public desktop disk IDs or extra image names.
|
|
54
|
-
Creation with `config.desktop.enabled: true` attaches before first boot and
|
|
55
|
-
honors normal `wait_ready`. Compatible custom/application images without a
|
|
56
|
-
prepared choice still support `install()` using the download-based recipe.
|
|
57
|
-
|
|
58
|
-
Use `client.disks.listSoftware({ workspace_id: workspaceId })` to browse software
|
|
59
|
-
compatible with a workspace's base OS. Desktop artifacts remain internal.
|
|
78
|
+
Browser and CLI tunnels use HTTPS/WSS on `workspace.oblien.com:443`. No public raw
|
|
79
|
+
VNC port is opened. Viewer URLs contain a credential in a fragment; do not log
|
|
80
|
+
or share them. Direct private runtime URLs also need the HTTP query credential
|
|
81
|
+
to load their authenticated viewer. OS login, where required, is separate;
|
|
82
|
+
`runtime.desktop.credentials()` is available only when the provider supplies it.
|
|
60
83
|
|
|
61
84
|
## CLI
|
|
62
85
|
|
|
63
|
-
|
|
86
|
+
Use the SDK/CLI build containing desktop session support:
|
|
64
87
|
|
|
65
88
|
```sh
|
|
66
|
-
npm install -g https://oblien.com/downloads/oblien-2.3.2.tgz
|
|
67
89
|
oblien login
|
|
68
|
-
oblien desktop
|
|
90
|
+
oblien desktop list WORKSPACE_ID
|
|
91
|
+
oblien desktop create WORKSPACE_ID --name Development --resolution 1920x1080
|
|
69
92
|
oblien desktop enable WORKSPACE_ID
|
|
70
|
-
oblien desktop vnc WORKSPACE_ID --port 5901
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
all desktop clients for that workspace.
|
|
77
|
-
|
|
78
|
-
Browser and native VNC traffic use the same authenticated WSS gateway route.
|
|
79
|
-
The Node tunnel sends its credential in an Authorization header, binds only to
|
|
80
|
-
local loopback and applies stream backpressure. No public raw VNC port is needed.
|
|
81
|
-
Token rotation or Runtime API disable revokes these connections too; obtain a
|
|
82
|
-
fresh runtime credential to reconnect. The package is downloadable independently
|
|
83
|
-
of npm registry publication.
|
|
84
|
-
|
|
85
|
-
## Native SSH/VNC apps
|
|
86
|
-
|
|
87
|
-
Enable desktop access, then issue an eight-hour desktop-only connection:
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
const connection = await client.workspaces.desktop.sshConnection(workspaceId);
|
|
91
|
-
// Or: await client.workspace(workspaceId).desktop.sshConnection();
|
|
92
|
-
// Treat connection.ssh.password as a secret; do not log it.
|
|
93
|
+
oblien desktop vnc WORKSPACE_ID --session DESKTOP_ID --port 5901
|
|
94
|
+
oblien desktop ssh WORKSPACE_ID --session DESKTOP_ID
|
|
95
|
+
oblien desktop update WORKSPACE_ID DESKTOP_ID --resolution 1600x900
|
|
96
|
+
oblien desktop stop WORKSPACE_ID DESKTOP_ID
|
|
97
|
+
oblien desktop start WORKSPACE_ID DESKTOP_ID
|
|
98
|
+
oblien desktop delete WORKSPACE_ID DESKTOP_ID
|
|
93
99
|
```
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
The response contains `ssh: { host, port, username, password, host_key_fingerprint }`,
|
|
100
|
-
`vnc: { host, port, authentication }` and `expires_at`. In a VNC app with built-in
|
|
101
|
-
SSH tunneling, use the supplied SSH settings and the VNC destination
|
|
102
|
-
`127.0.0.1:5900`. SSH password authentication grants access only to this desktop,
|
|
103
|
-
with no shell or arbitrary forwarding. Verify the host fingerprint on first use.
|
|
104
|
-
No local CLI relay or enabled guest SSH service is required for this path.
|
|
105
|
-
|
|
106
|
-
Expiry closes active connections. Desktop disable rejects access while disabled;
|
|
107
|
-
re-enable permits unexpired credentials again. Runtime token rotation permanently
|
|
108
|
-
revokes previous desktop credentials. Issuing another connection does not revoke
|
|
109
|
-
older ones. The OS login, if required, uses separate account credentials.
|
|
110
|
-
|
|
111
|
-
Browser/CLI WSS stays on `workspace.oblien.com` port 443, and managed SSH uses
|
|
112
|
-
`ssh.oblien.com` port 22. Both reach the same private runtime desktop endpoint.
|
|
113
|
-
There is no public raw VNC port. See the
|
|
114
|
-
[native connection guide](https://oblien.com/docs/workspace/desktop#mobile-and-remote-devices)
|
|
115
|
-
for client settings, expiry, security and clipboard limitations.
|
|
101
|
+
Keep the `vnc` command running; Ctrl+C closes its local tunnel. The normal `install`,
|
|
102
|
+
`installation`, `status`, `enable`, `disable` and `credentials` commands remain.
|
|
103
|
+
REST session routes work independently of SDK publication; see the
|
|
104
|
+
[public desktop guide](https://oblien.com/docs/workspace/desktop#saved-desktops).
|
package/docs/namespaces.md
CHANGED
|
@@ -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
|
+
Current compute uses 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:
|
|
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
|
|
42
|
-
|
|
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
|
|
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: '
|
|
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
|
-
|
|
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.
|
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
|
|
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`.
|