oblien 2.2.45 → 2.3.2

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 (82) hide show
  1. package/README.md +2 -0
  2. package/dist/billing.d.ts +209 -0
  3. package/dist/billing.d.ts.map +1 -0
  4. package/dist/billing.js +276 -0
  5. package/dist/billing.js.map +1 -0
  6. package/dist/cli/commands/desktop.d.ts +3 -0
  7. package/dist/cli/commands/desktop.d.ts.map +1 -0
  8. package/dist/cli/commands/desktop.js +41 -0
  9. package/dist/cli/commands/desktop.js.map +1 -0
  10. package/dist/cli/commands/workspaces.d.ts.map +1 -1
  11. package/dist/cli/commands/workspaces.js +9 -1
  12. package/dist/cli/commands/workspaces.js.map +1 -1
  13. package/dist/cli/index.js +5 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/client.d.ts +6 -0
  16. package/dist/client.d.ts.map +1 -1
  17. package/dist/client.js +7 -0
  18. package/dist/client.js.map +1 -1
  19. package/dist/http-error.d.ts.map +1 -1
  20. package/dist/http-error.js +4 -1
  21. package/dist/http-error.js.map +1 -1
  22. package/dist/http.d.ts.map +1 -1
  23. package/dist/http.js +4 -7
  24. package/dist/http.js.map +1 -1
  25. package/dist/index.d.ts +3 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp/tools.d.ts.map +1 -1
  30. package/dist/mcp/tools.js +2 -0
  31. package/dist/mcp/tools.js.map +1 -1
  32. package/dist/resources/desktop.d.ts +25 -0
  33. package/dist/resources/desktop.d.ts.map +1 -0
  34. package/dist/resources/desktop.js +12 -0
  35. package/dist/resources/desktop.js.map +1 -0
  36. package/dist/runtime/desktop-tunnel.d.ts +7 -0
  37. package/dist/runtime/desktop-tunnel.d.ts.map +1 -0
  38. package/dist/runtime/desktop-tunnel.js +56 -0
  39. package/dist/runtime/desktop-tunnel.js.map +1 -0
  40. package/dist/runtime/desktop.d.ts +37 -0
  41. package/dist/runtime/desktop.d.ts.map +1 -0
  42. package/dist/runtime/desktop.js +41 -0
  43. package/dist/runtime/desktop.js.map +1 -0
  44. package/dist/runtime-http.js +1 -1
  45. package/dist/runtime-http.js.map +1 -1
  46. package/dist/runtime.d.ts +12 -1
  47. package/dist/runtime.d.ts.map +1 -1
  48. package/dist/runtime.js +24 -2
  49. package/dist/runtime.js.map +1 -1
  50. package/dist/types/billing.d.ts +187 -0
  51. package/dist/types/billing.d.ts.map +1 -0
  52. package/dist/types/billing.js +10 -0
  53. package/dist/types/billing.js.map +1 -0
  54. package/dist/types/common.d.ts +1 -0
  55. package/dist/types/common.d.ts.map +1 -1
  56. package/dist/types/index.d.ts +6 -3
  57. package/dist/types/index.d.ts.map +1 -1
  58. package/dist/types/notifications.d.ts +8 -0
  59. package/dist/types/notifications.d.ts.map +1 -1
  60. package/dist/types/runtime.d.ts +48 -0
  61. package/dist/types/runtime.d.ts.map +1 -1
  62. package/dist/types/webhooks.d.ts +1 -1
  63. package/dist/types/webhooks.d.ts.map +1 -1
  64. package/dist/types/workspace-resources.d.ts +18 -0
  65. package/dist/types/workspace-resources.d.ts.map +1 -1
  66. package/dist/types/workspace.d.ts +61 -1
  67. package/dist/types/workspace.d.ts.map +1 -1
  68. package/dist/workspace-handle.d.ts +6 -1
  69. package/dist/workspace-handle.d.ts.map +1 -1
  70. package/dist/workspace-handle.js +8 -0
  71. package/dist/workspace-handle.js.map +1 -1
  72. package/dist/workspace.d.ts +11 -3
  73. package/dist/workspace.d.ts.map +1 -1
  74. package/dist/workspace.js +86 -7
  75. package/dist/workspace.js.map +1 -1
  76. package/docs/billing.md +137 -0
  77. package/docs/desktop.md +83 -0
  78. package/docs/errors.md +7 -1
  79. package/docs/notifications.md +15 -0
  80. package/docs/workspace-limit-report.md +34 -0
  81. package/docs/workspaces.md +30 -0
  82. package/package.json +2 -1
package/dist/workspace.js CHANGED
@@ -1,7 +1,9 @@
1
+ import { OblienError } from './error.js';
1
2
  import { Runtime } from './runtime.js';
2
3
  import { LifecycleResource } from './resources/lifecycle.js';
3
4
  import { NetworkResource } from './resources/network.js';
4
5
  import { SshResource } from './resources/ssh.js';
6
+ import { DesktopResource } from './resources/desktop.js';
5
7
  import { PublicAccessResource } from './resources/public-access.js';
6
8
  import { ResourcesResource } from './resources/resources.js';
7
9
  import { SnapshotsResource } from './resources/snapshots.js';
@@ -50,6 +52,7 @@ export class Workspace {
50
52
  network;
51
53
  /** SSH access - enable, disable, set password/key. */
52
54
  ssh;
55
+ desktop;
53
56
  /** Public port access - expose and revoke ports. */
54
57
  publicAccess;
55
58
  /** Resources - CPU, memory, disk allocation. */
@@ -80,6 +83,7 @@ export class Workspace {
80
83
  this.lifecycle = new LifecycleResource(this._http);
81
84
  this.network = new NetworkResource(this._http);
82
85
  this.ssh = new SshResource(this._http);
86
+ this.desktop = new DesktopResource(this._http);
83
87
  this.publicAccess = new PublicAccessResource(this._http);
84
88
  this.resources = new ResourcesResource(this._http);
85
89
  this.snapshots = new SnapshotsResource(this._http);
@@ -93,11 +97,14 @@ export class Workspace {
93
97
  this.domains = new DomainsResource(this._http);
94
98
  }
95
99
  // ── CRUD ──────────────────────────────────────────────────────────
96
- /** Create a new workspace. */
97
- async create(params = {}) {
100
+ /** Create a workspace; wait for its runtime unless wait_ready is false. */
101
+ async create(params = {}, options = {}) {
98
102
  // Flatten convenience resource fields into config so the backend sees them.
99
103
  // Backend extracts cpus/memory_mb/disk_size_mb from config.
100
- const { cpus, memory_mb, disk_size_mb, ...rest } = params;
104
+ const { cpus, memory_mb, disk_size_mb, wait_ready = true, ready_timeout_seconds = 600, ...rest } = params;
105
+ const timeoutMs = options.timeoutMs ?? ready_timeout_seconds * 1000;
106
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
107
+ throw new RangeError('Readiness timeout must be positive');
101
108
  const config = { ...rest.config };
102
109
  if (cpus !== undefined)
103
110
  config.cpus = cpus;
@@ -105,8 +112,80 @@ export class Workspace {
105
112
  config.memory_mb = memory_mb;
106
113
  if (disk_size_mb !== undefined)
107
114
  config.disk_size_mb = disk_size_mb;
108
- const body = { ...rest, config };
109
- const res = await this._http.request({ method: 'POST', path: this._base, body });
115
+ const body = { ...rest, config, wait_ready: false };
116
+ const res = await this._http.request({ method: 'POST', path: this._base, body, signal: options.signal });
117
+ if (!wait_ready)
118
+ return res.workspace;
119
+ return this._waitUntilReady(res.workspace.id, { ...options, timeoutMs }, res.workspace);
120
+ }
121
+ /** Wait for an accepted creation using short status requests. */
122
+ waitUntilReady(workspaceId, options = {}) {
123
+ return this._waitUntilReady(workspaceId, options);
124
+ }
125
+ async _waitUntilReady(workspaceId, options, initial) {
126
+ const timeoutMs = options.timeoutMs ?? 600_000;
127
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
128
+ throw new RangeError('Readiness timeout must be positive');
129
+ const controller = new AbortController();
130
+ const abort = () => controller.abort(options.signal?.reason);
131
+ options.signal?.addEventListener('abort', abort, { once: true });
132
+ if (options.signal?.aborted)
133
+ abort();
134
+ let timedOut = false;
135
+ const timeout = setTimeout(() => { timedOut = true; controller.abort(); }, timeoutMs);
136
+ let workspace = initial;
137
+ try {
138
+ for (;;) {
139
+ controller.signal.throwIfAborted();
140
+ if (!workspace) {
141
+ try {
142
+ const res = await this._http.request({
143
+ method: 'GET', path: `${this._base}/${encodeURIComponent(workspaceId)}`, signal: controller.signal,
144
+ });
145
+ workspace = res.workspace;
146
+ }
147
+ catch (error) {
148
+ // A short API outage must not turn an accepted creation into failure.
149
+ if (!(error instanceof TypeError) && !(error.status >= 500) && error.status !== 429)
150
+ throw error;
151
+ }
152
+ }
153
+ const state = workspace?.provisioning;
154
+ if (state?.phase === 'deleting')
155
+ throw new OblienError('Workspace creation was cancelled', 409, 'WORKSPACE_CREATION_CANCELLED', { workspace_id: workspaceId });
156
+ if (state?.state === 'failed')
157
+ throw new OblienError(state.error?.message || 'Workspace creation failed', 422, state.error?.code || 'CREATE_FAILED', { workspace_id: workspaceId, workspace });
158
+ if (workspace?.ready === true || (!state && (workspace?.info?.is_running || workspace?.info?.status === 'running')))
159
+ return workspace;
160
+ if (workspace && state?.state === 'ready' && !workspace.ready)
161
+ throw new OblienError('Workspace creation completed, but the workspace has stopped', 409, 'WORKSPACE_STOPPED', { workspace_id: workspaceId, workspace });
162
+ await new Promise((resolve, reject) => {
163
+ const interrupted = () => { clearTimeout(timer); reject(controller.signal.reason); };
164
+ const timer = setTimeout(() => { controller.signal.removeEventListener('abort', interrupted); resolve(); }, 2000);
165
+ controller.signal.addEventListener('abort', interrupted, { once: true });
166
+ if (controller.signal.aborted)
167
+ interrupted();
168
+ });
169
+ workspace = undefined;
170
+ }
171
+ }
172
+ catch (error) {
173
+ if (timedOut)
174
+ throw new OblienError('Timed out waiting for workspace readiness; creation continues', undefined, 'WORKSPACE_READY_TIMEOUT', { workspace_id: workspaceId });
175
+ if (options.signal?.aborted)
176
+ throw new OblienError('Stopped waiting for workspace readiness; creation continues', undefined, 'WORKSPACE_WAIT_ABORTED', { workspace_id: workspaceId });
177
+ throw error;
178
+ }
179
+ finally {
180
+ clearTimeout(timeout);
181
+ options.signal?.removeEventListener('abort', abort);
182
+ }
183
+ }
184
+ /** Retry a failed creation with its existing ID and configuration. */
185
+ async retryCreation(workspaceId) {
186
+ const res = await this._http.request({
187
+ method: 'POST', path: `${this._base}/${encodeURIComponent(workspaceId)}/provisioning/retry`,
188
+ });
110
189
  return res.workspace;
111
190
  }
112
191
  /** List workspaces with optional pagination / filters. */
@@ -196,7 +275,7 @@ export class Workspace {
196
275
  if (!options?.force) {
197
276
  const cached = this._runtimes.get(workspaceId);
198
277
  if (cached && (Date.now() - cached.fetchedAt) < this._tokenTtlMs) {
199
- return cached.runtime;
278
+ return options?.target ? cached.runtime.forTarget(options.target) : cached.runtime;
200
279
  }
201
280
  }
202
281
  /* ── 2. Check status (lightweight GET, no side-effects) ── */
@@ -218,7 +297,7 @@ export class Workspace {
218
297
  }
219
298
  const rt = new Runtime({ token });
220
299
  this._runtimes.set(workspaceId, { runtime: rt, fetchedAt: Date.now() });
221
- return rt;
300
+ return options?.target ? rt.forTarget(options.target) : rt;
222
301
  }
223
302
  /**
224
303
  * Set the token TTL used by the runtime cache.
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ # Namespace billing
2
+
3
+ Available in `oblien@2.3.0`, with the matching namespace billing API deployment.
4
+ Each customer uses a namespace with its own subscription, Stripe customer, quota,
5
+ and billing portal. Keep your `admin` or `billing` API key on your server. Resolve
6
+ the namespace from the authenticated customer's record before calling these methods.
7
+ Namespace/workspace tokens cannot access billing.
8
+ Do not reassign a customer's namespace slug to someone else: its billing history
9
+ stays attached to that owner/namespace identity.
10
+
11
+ ```typescript
12
+ import Oblien from 'oblien';
13
+
14
+ const client = new Oblien({
15
+ clientId: process.env.OBLIEN_CLIENT_ID!,
16
+ clientSecret: process.env.OBLIEN_CLIENT_SECRET!,
17
+ });
18
+ const namespace = authenticatedCustomer.namespace;
19
+ ```
20
+
21
+ ## Hosted subscriptions and top-ups
22
+
23
+ ```typescript
24
+ const { plans, creditPacks } = await client.billing.catalog();
25
+ const checkout = await client.billing.checkout({
26
+ namespace,
27
+ kind: 'subscription',
28
+ planTierId: plans.find(plan => plan.tierId === 'pro')!.tierId,
29
+ billingInterval: 'monthly',
30
+ customer: { email: authenticatedCustomer.email },
31
+ idempotencyKey: `subscription-${orderId}`,
32
+ successUrl: 'https://app.example.com/billing/success',
33
+ cancelUrl: 'https://app.example.com/billing',
34
+ });
35
+ // Redirect to checkout.url. Wait for the paid entitlement before granting access.
36
+
37
+ const entitlement = await client.billing.entitlement(namespace);
38
+ const balance = await client.billing.balance(namespace);
39
+
40
+ const topup = await client.billing.checkout({
41
+ namespace,
42
+ kind: 'topup',
43
+ packId: creditPacks[0].packId,
44
+ idempotencyKey: `topup-${orderId}`,
45
+ });
46
+ ```
47
+
48
+ Use catalog IDs and prices. Return URLs must be host-allowlisted by the operator;
49
+ otherwise they fall back to Oblien's dashboard. Optional `customer` details apply
50
+ to the first namespace checkout, without copying the API-key owner's details.
51
+ Reuse an idempotency key only when retrying the identical request.
52
+
53
+ Paid subscriptions provision the namespace and set its quota. Renewals reset usage
54
+ once per cycle; purchased top-ups increase the ceiling and survive renewal.
55
+ Top-ups, renewals, and funded policy changes clear suspensions caused by billing;
56
+ manual suspensions stay in place. Workspaces can then be started explicitly.
57
+
58
+ ## Customer billing management
59
+
60
+ ```typescript
61
+ const portal = await client.billing.portal({
62
+ namespace,
63
+ returnUrl: 'https://app.example.com/billing',
64
+ });
65
+ // Redirect to portal.url for invoices, payment methods, contact details, cancellation.
66
+
67
+ const { subscription } = await client.billing.subscription(namespace);
68
+ // subscription === null if this namespace has never subscribed.
69
+ // subscription.cancelAtPeriodEnd drives "cancels on…" / "keep subscription" UI.
70
+
71
+ await client.billing.cancelSubscription(namespace); // Ends renewal after the paid period.
72
+ await client.billing.resumeSubscription(namespace); // Clears a scheduled cancellation.
73
+ ```
74
+
75
+ Every management method addresses exactly one owner/namespace pair. `portal()`
76
+ requires `namespace`; older local integrations using `portal({ returnUrl })` must
77
+ add it. The owner dashboard uses its separate `/credits/manage` endpoint.
78
+
79
+ Cancel/resume are safe to repeat. Cancellation keeps paid access through `periodEnd`.
80
+ An ended subscription must be purchased again through checkout. Tier changes also
81
+ use a new paid checkout: it replaces only this namespace's subscription and starts a
82
+ full-price cycle; there is no automatic proration. Portal tier switching is disabled.
83
+
84
+ | Error code | Meaning |
85
+ | --- | --- |
86
+ | `no_customer` | This namespace has no Stripe customer yet. |
87
+ | `billing_customer_conflict` | Legacy billing shares a Stripe customer; the operator must separate it. |
88
+ | `no_subscription` | No subscription to cancel/resume. |
89
+ | `subscription_ended` | Start a new checkout instead of resuming. |
90
+ | `billing_identity_conflict` | Stored billing and Stripe identity disagree. |
91
+
92
+ ## Bring your own payments
93
+
94
+ ```typescript
95
+ await client.billing.setDefaults({
96
+ quotaLimit: 1000, overdraft: 0, suspendThreshold: 0, autoApply: true,
97
+ });
98
+ await client.billing.setPolicy(namespace, {
99
+ quotaLimit: 5000, overdraft: 100, suspendThreshold: 100,
100
+ onOverdraftAction: 'stop_workspaces',
101
+ });
102
+ const policy = await client.billing.policy(namespace);
103
+
104
+ // Call after your next payment cycle clears. Reuse the same timestamp on retry.
105
+ const reset = await client.billing.resetQuota(namespace, {
106
+ periodEnd: '2026-10-01T00:00:00Z',
107
+ });
108
+ // reset.applied is false for the same or an older cycle.
109
+ ```
110
+
111
+ Setting policy preserves usage. `resetQuota()` resets usage and threshold markers,
112
+ preserving purchased credits and the policy. It returns `subscription_managed` for
113
+ a live Oblien-hosted subscription, whose paid invoices reset quota automatically.
114
+ Defaults apply to newly created namespaces. Without a policy/default, a namespace
115
+ is uncapped. `overdraft` must not exceed `suspendThreshold` when both are set.
116
+
117
+ ## Access and reconciliation
118
+
119
+ `entitlement()` returns `active`, `past_due`, `credit_exhausted`, or `canceled`.
120
+
121
+ The paid tier and period belong to that namespace's subscription. An account or
122
+ sibling namespace subscription cannot supply them. A namespace that has never
123
+ subscribed returns `tierId: 'free'` with null period dates; its policy determines
124
+ available credit. Zero-credit defaults are initialized by both namespace creation
125
+ and ensure, so a new namespace immediately returns `credit_exhausted`. Usage and
126
+ balances preserve fractional credits.
127
+ `balance()` checks suspension and spending capacity; a subscription-only product
128
+ must also check entitlement and whether a subscription exists.
129
+
130
+ Subscribe to `payment.succeeded`, `entitlement.changed`, `subscription.renewed`,
131
+ `subscription.updated`, `subscription.past_due`, `subscription.canceled`,
132
+ `subscription.tier_changed`, `namespace.suspended`, and `namespace.restored` using
133
+ `client.webhooks`. Verify the signature on raw bytes and deduplicate event IDs.
134
+ Webhook delivery is best effort: reconcile with `entitlement()` and
135
+ `subscription()` when the customer returns to billing or an event is missed.
136
+
137
+ [Full API contract](https://oblien.com/docs/api/billing)
@@ -0,0 +1,83 @@
1
+ # Remote desktop
2
+
3
+ Desktop is an image capability. The same API works for Mac and Linux desktop
4
+ providers. Access defaults off and changes without reboot. Disabling it closes
5
+ desktop sessions and preserves terminal/SSH/workloads. The saved choice survives
6
+ workspace restart.
7
+
8
+ ```ts
9
+ const runtime = await client.workspaces.runtime(workspaceId);
10
+ if ((await runtime.desktop.status()).supported) {
11
+ await runtime.desktop.enable();
12
+ const viewerUrl = runtime.desktop.url(); // Credential-bearing URL: keep private.
13
+ const tunnel = await runtime.desktop.tunnel({ port: 5901 }); // Node.js only
14
+ // Connect a VNC client to tunnel.url (vnc://127.0.0.1:5901).
15
+ await tunnel.close();
16
+ await runtime.desktop.disable();
17
+ }
18
+ ```
19
+
20
+ Status includes `supported`, `enabled`, `available`, `credentials` and
21
+ `transports`. If `credentials` is true, `runtime.desktop.credentials()` returns
22
+ the image's OS account. For Mac this is `oblien` with its per-workspace password,
23
+ also used by SSH. The method requires enabled desktop access.
24
+
25
+ Creation accepts `config.desktop: { enabled: true }`. Live changes use these
26
+ methods without changing CPU, RAM or boot settings. `forTarget()` changes command
27
+ and file targets, while desktop continues to address the workspace image.
28
+
29
+ ## CLI
30
+
31
+ The desktop-enabled 2.3.2 build is an official downloadable package:
32
+
33
+ ```sh
34
+ npm install -g https://oblien.com/downloads/oblien-2.3.2.tgz
35
+ oblien login
36
+ oblien desktop status WORKSPACE_ID
37
+ oblien desktop enable WORKSPACE_ID
38
+ oblien desktop vnc WORKSPACE_ID --port 5901
39
+ ```
40
+
41
+ Keep the command running and open `vnc://127.0.0.1:5901` in a VNC client.
42
+ `oblien desktop credentials WORKSPACE_ID` retrieves the optional OS login account.
43
+ Ctrl+C closes the local tunnel. `oblien desktop disable WORKSPACE_ID` disconnects
44
+ all desktop clients for that workspace.
45
+
46
+ Browser and native VNC traffic use the same authenticated WSS gateway route.
47
+ The Node tunnel sends its credential in an Authorization header, binds only to
48
+ local loopback and applies stream backpressure. No public raw VNC port is needed.
49
+ Token rotation or Runtime API disable revokes these connections too; obtain a
50
+ fresh runtime credential to reconnect. The package is downloadable independently
51
+ of npm registry publication.
52
+
53
+ ## Native SSH/VNC apps
54
+
55
+ Enable desktop access, then issue an eight-hour desktop-only connection:
56
+
57
+ ```ts
58
+ const connection = await client.workspaces.desktop.sshConnection(workspaceId);
59
+ // Or: await client.workspace(workspaceId).desktop.sshConnection();
60
+ // Treat connection.ssh.password as a secret; do not log it.
61
+ ```
62
+
63
+ ```sh
64
+ oblien desktop ssh WORKSPACE_ID
65
+ ```
66
+
67
+ The response contains `ssh: { host, port, username, password, host_key_fingerprint }`,
68
+ `vnc: { host, port, authentication }` and `expires_at`. In a VNC app with built-in
69
+ SSH tunneling, use the supplied SSH settings and the VNC destination
70
+ `127.0.0.1:5900`. SSH password authentication grants access only to this desktop,
71
+ with no shell or arbitrary forwarding. Verify the host fingerprint on first use.
72
+ No local CLI relay or enabled guest SSH service is required for this path.
73
+
74
+ Expiry closes active connections. Desktop disable rejects access while disabled;
75
+ re-enable permits unexpired credentials again. Runtime token rotation permanently
76
+ revokes previous desktop credentials. Issuing another connection does not revoke
77
+ older ones. The OS login, if required, uses separate account credentials.
78
+
79
+ Browser/CLI WSS stays on `workspace.oblien.com` port 443, and managed SSH uses
80
+ `ssh.oblien.com` port 22. Both reach the same private runtime desktop endpoint.
81
+ There is no public raw VNC port. See the
82
+ [native connection guide](https://oblien.com/docs/workspace/desktop#mobile-and-remote-devices)
83
+ for client settings, expiry, security and clipboard limitations.
package/docs/errors.md CHANGED
@@ -27,8 +27,14 @@ try {
27
27
  | `AuthenticationError` | 401 | Invalid or missing credentials |
28
28
  | `PaymentRequiredError` | 402 | Credit quota exceeded |
29
29
  | `NotFoundError` | 404 | Resource does not exist |
30
- | `ConflictError` | 409 | Resource in wrong state |
30
+ | `ConflictError` | 409 | Resource in wrong state or workspace/namespace/pool limit reached |
31
31
  | `ValidationError` | 422 | Invalid parameters |
32
32
  | `RateLimitError` | 429 | Too many requests |
33
33
 
34
34
  All subclasses extend `OblienError`, so a single `instanceof OblienError` catch handles everything while still exposing `.code`/`.message`/`.details`/`.requestId`.
35
+
36
+ Legacy API versions may return HTTP 200 with `success: false` for workspace limits.
37
+ The SDK rejects these responses too. The three limit codes
38
+ `SANDBOX_LIMIT_REACHED`, `NAMESPACE_LIMIT_REACHED`, and `POOL_LIMIT_REACHED` become
39
+ `ConflictError`, with the original HTTP status retained in `.status`. HTTP failures
40
+ are also rejected when their JSON body omits `success: false`.
@@ -37,4 +37,19 @@ await nt.send(token.token, { title: 'Build done', body: 'Agent finished', data:
37
37
 
38
38
  Dead device tokens (app uninstalled) are auto-pruned on send.
39
39
 
40
+ Inspect `failed` and `errors` even when the request succeeds: acceptance by Oblien
41
+ does not mean FCM delivered to a device.
42
+
43
+ ```typescript
44
+ const result = await nt.send(token.token, { title: 'Build done' });
45
+ for (const error of result.errors ?? []) {
46
+ console.error(error.code, error.message, error.count);
47
+ }
48
+ ```
49
+
50
+ The API returns sanitized Firebase codes/messages, such as
51
+ `messaging/third-party-auth-error` for an APNs authentication failure. Older API
52
+ deployments return only the delivery counters; deploy the API update to receive
53
+ `errors`.
54
+
40
55
  **Full reference:** [Notifications concept](https://oblien.com/docs/concepts/notifications) · [API](https://oblien.com/docs/api/notifications)
@@ -0,0 +1,34 @@
1
+ # Openship workspace-limit HTTP status report
2
+
3
+ Reported 2026-09-17. Openship already rejects this response safely; it is not an
4
+ independent release blocker for Openship.
5
+
6
+ Some API deployments returned HTTP 200 when workspace creation failed:
7
+
8
+ ```json
9
+ {
10
+ "success": false,
11
+ "error": "SANDBOX_LIMIT_REACHED",
12
+ "code": "SANDBOX_LIMIT_REACHED",
13
+ "message": "Workspace count limit reached.",
14
+ "current": 3,
15
+ "max": 3
16
+ }
17
+ ```
18
+
19
+ Expected behavior is HTTP 409 with the failure code and quota details. The API now
20
+ maps workspace, namespace, and owned-pool limits to 409. A namespace admission
21
+ failure also now sets `success: false`, so the response cannot take the success path.
22
+
23
+ The SDK patch retains compatibility with legacy HTTP 200 failure envelopes, maps
24
+ these limit codes to `ConflictError`, and preserves the actual response status.
25
+ It also rejects non-2xx JSON responses that omit `success: false`. Creation failures
26
+ do not enter readiness polling or issue a second create request.
27
+
28
+ Verification: `npm test` passes all 19 SDK tests, including
29
+ `tests/http-errors.test.mjs` for legacy 200, current 409, uppercase error-only codes,
30
+ 403/500 JSON responses, and successful asynchronous creation.
31
+
32
+ This report and patch are recorded in the SDK repository for maintainers. No external
33
+ issue or team message has been sent from this environment. The public npm version
34
+ checked during this work is 2.3.0; these SDK changes require the next SDK release.
@@ -1,5 +1,18 @@
1
1
  # Workspaces
2
2
 
3
+ `create()` waits for the workspace's default runtime. To return its ID immediately:
4
+
5
+ ```ts
6
+ const pending = await client.workspaces.create({
7
+ image: 'oblien/ubuntu:24.04',
8
+ wait_ready: false,
9
+ idempotency_key: 'my-create-request',
10
+ });
11
+ const ready = await client.workspaces.waitUntilReady(pending.id, { timeoutMs: 300_000 });
12
+ ```
13
+
14
+ Read `workspace.provisioning` for progress and failure details, and `workspace.ready` for readiness. `waitUntilReady` supports `signal`; a timeout or abort stops waiting while creation continues. Errors include `details.workspace_id`. Reuse the same `idempotency_key` if a create response is lost. Failed creation can be retried with `retryCreation(id)` or deleted with `delete(id)`. A deletion accepted with `accepted: true` completes in the background.
15
+
3
16
  A workspace is a hardware-isolated microVM that boots in under a second from any Docker image. It's the only primitive in Oblien — everything else (pages, proxies, domains) hangs off a workspace or the account.
4
17
 
5
18
  `client.workspaces` is the control-plane resource: create, configure, power, and destroy workspaces, plus a tree of sub-resources. To interact with a *running* workspace's filesystem/exec/terminal, see **[Runtime](./runtime.md)**.
@@ -27,6 +40,12 @@ await ws.delete(workspace.id);
27
40
 
28
41
  Creating in a namespace enforces that namespace's **resource limits** (max workspaces, per-workspace vCPU/RAM/disk) atomically, and **status** (a suspended/over-quota namespace rejects new workspaces). See **[Namespaces](./namespaces.md)**.
29
42
 
43
+ Workspace count, namespace, and owned resource pool limits return HTTP 409 with
44
+ `SANDBOX_LIMIT_REACHED`, `NAMESPACE_LIMIT_REACHED`, or `POOL_LIMIT_REACHED`. The SDK
45
+ throws `ConflictError` for these codes, including older API responses that incorrectly
46
+ used HTTP 200 with `success: false`. It preserves the actual HTTP status in
47
+ `error.status` and rejects before polling for readiness.
48
+
30
49
  ## Power
31
50
 
32
51
  ```typescript
@@ -37,6 +56,15 @@ await ws.pause(id); // freeze to disk
37
56
  await ws.resume(id); // thaw
38
57
  ```
39
58
 
59
+ During billing or manual namespace suspension, scoped credentials can still inspect,
60
+ stop, and delete their own workspaces. Create, start, restart, resume, and other
61
+ mutations return `403 namespace_suspended`. Funding can restore a billing suspension;
62
+ manual suspension requires explicit namespace activation. Restoration leaves
63
+ workspaces stopped until the customer starts them.
64
+
65
+ Stop is safe to retry when automatic exhaustion or an earlier request has already
66
+ stopped the VM. The API returns success only after the VM node confirms that state.
67
+
40
68
  ## Scoped handle
41
69
 
42
70
  Bind to one workspace so you never pass the ID again:
@@ -79,4 +107,6 @@ Accessed as namespaces on `client.workspaces`:
79
107
  | `logs` | Boot and command logs |
80
108
  | `images` | Available base images |
81
109
 
110
+ Native macOS SSH uses public-key authentication and the `oblien` login account. Save a public key with `client.workspaces.ssh.setKey(id, { public_key })`, then call `client.workspaces.ssh.enable(id)`. SSH status includes `auth_methods` and the SSH/SCP connection commands. Public SSH can be disabled without affecting the Mac runtime or its private boot connection.
111
+
82
112
  **Full reference:** [API docs](https://oblien.com/docs/api/workspaces)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oblien",
3
- "version": "2.2.45",
3
+ "version": "2.3.2",
4
4
  "description": "Official TypeScript SDK for the Oblien Workspace API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,6 +30,7 @@
30
30
  "LICENSE"
31
31
  ],
32
32
  "scripts": {
33
+ "test": "npm run build && node --test tests/*.test.mjs",
33
34
  "build": "tsc",
34
35
  "dev": "tsc --watch",
35
36
  "clean": "rm -rf dist",