@sealant/sdk-next 0.39.0-next.712 → 0.39.0-next.714
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 +9 -2
- package/dist/client.js +9 -1
- package/dist/effect/api-client.d.ts +74 -2
- package/dist/effect/operations.d.ts +23 -1
- package/dist/effect/operations.js +2 -0
- package/dist/facade/workspace.js +4 -1
- package/dist/internal/blueprint.d.ts +1 -0
- package/dist/internal/blueprint.js +1 -0
- package/dist/internal/features.d.ts +2 -0
- package/dist/internal/features.js +2 -0
- package/dist/internal/process-user.d.ts +6 -0
- package/dist/internal/process-user.js +11 -0
- package/dist/types.d.ts +39 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -96,9 +96,16 @@ if (
|
|
|
96
96
|
- `workspace.processUser()` reads `supported`, `unsupported` or `unknown` from the image's sealantd;
|
|
97
97
|
`launch.processUser` has it after `ready()`. The call itself asks the running daemon, whose answer
|
|
98
98
|
decides.
|
|
99
|
+
- `users.bindPerson(userId, { id, uid, home })` binds a user's person once; a different binding, or
|
|
100
|
+
a person id or uid another user holds, rejects (`409`).
|
|
101
|
+
`create({ credentialsHome, sshAsOwner: true })` runs the workspace's SSH sessions, VS Code
|
|
102
|
+
Remote-SSH included, as the owner's bound person: the create's owner map and `credentialsHome`
|
|
103
|
+
must agree with the binding (`403` otherwise). No caller names the user. `workspace.sshAsRoot()`
|
|
104
|
+
sets them back to root. A create with it is refused (`ssh-user-unsupported`) with nothing sent
|
|
105
|
+
when the control plane does not report `workspaceSshUser`.
|
|
99
106
|
- `sealant.features()` reports what the control plane can do: `processUserRoutes`, `dotfilesApply`,
|
|
100
|
-
`credentialsPartialPut`, `credentialsPiOpencode` and `
|
|
101
|
-
reading the control plane's version.
|
|
107
|
+
`credentialsPartialPut`, `credentialsPiOpencode`, `captureOwnerMap` and `workspaceSshUser`. Detect
|
|
108
|
+
them instead of reading the control plane's version.
|
|
102
109
|
|
|
103
110
|
## Typed record events
|
|
104
111
|
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { archiveConnectedAccountOp, archiveSshKeyOp, cancelWorkspaceCreateOp, createAccessTokenOp, createConnectedAccountOp, createSshKeyOp, createWorkspaceOp, ensureUserOp, getRunOp, getSetupStateOp, getUserOp, getWorkspaceCreateOp, getWorkspaceOp, inferenceRespondOp, inspectWorkspaceImageOp, listConnectedAccountsOp, listSshKeysOp, listWorkspacesOp, } from "./effect/operations.js";
|
|
1
|
+
import { archiveConnectedAccountOp, archiveSshKeyOp, cancelWorkspaceCreateOp, createAccessTokenOp, createConnectedAccountOp, createSshKeyOp, createWorkspaceOp, ensureUserOp, getRunOp, getSetupStateOp, getUserOp, bindUserPersonOp, getWorkspaceCreateOp, getWorkspaceOp, inferenceRespondOp, inspectWorkspaceImageOp, listConnectedAccountsOp, listSshKeysOp, listWorkspacesOp, } from "./effect/operations.js";
|
|
2
2
|
import { runHarness, startHarness } from "./effect/run-harness.js";
|
|
3
3
|
import { makeSdkRuntime } from "./effect/runtime.js";
|
|
4
4
|
import { SealantError } from "./errors.js";
|
|
@@ -10,6 +10,7 @@ import { parseTtlSeconds } from "./internal/duration.js";
|
|
|
10
10
|
import { readFeatures } from "./internal/features.js";
|
|
11
11
|
import { imageSpecKey } from "./internal/image-key.js";
|
|
12
12
|
import { buildInferenceRespondRequest, mapInferenceResponse } from "./internal/inference.js";
|
|
13
|
+
import { requireSshUser } from "./internal/process-user.js";
|
|
13
14
|
import { mapSshKey, mapWorkspaceSshInfo } from "./internal/ssh.js";
|
|
14
15
|
/** An idempotent create's state as the SDK reports it (an unknown wire state fails closed). */
|
|
15
16
|
const toCreateState = (wire) => ({
|
|
@@ -63,6 +64,9 @@ export class Sealant {
|
|
|
63
64
|
/** Workspace lifecycle: create, fetch, and list live environments. */
|
|
64
65
|
workspaces = {
|
|
65
66
|
create: async (options) => {
|
|
67
|
+
if (options.sshAsOwner === true) {
|
|
68
|
+
await requireSshUser(this.#ctx);
|
|
69
|
+
}
|
|
66
70
|
const { payload } = buildCreateWorkspaceRequest(options, this.#ctx.config);
|
|
67
71
|
const created = await this.#runtime.run(createWorkspaceOp(payload));
|
|
68
72
|
const workspace = makeWorkspace(this.#ctx, {
|
|
@@ -227,6 +231,10 @@ export class Sealant {
|
|
|
227
231
|
const wire = await this.#runtime.run(getUserOp(userId));
|
|
228
232
|
return { userId: wire.userId, email: wire.email, name: wire.name, createdAt: wire.createdAt };
|
|
229
233
|
},
|
|
234
|
+
bindPerson: async (userId, person) => {
|
|
235
|
+
const wire = await this.#runtime.run(bindUserPersonOp(userId, { id: person.id, uid: person.uid, home: person.home }));
|
|
236
|
+
return { userId: wire.userId, person: wire.person, created: wire.created };
|
|
237
|
+
},
|
|
230
238
|
};
|
|
231
239
|
/** This client's owner's Claude / Codex / GitHub accounts. Secrets go in; none come out. */
|
|
232
240
|
connectedAccounts = {
|
|
@@ -1147,6 +1147,8 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1147
1147
|
readonly credentialsPartialPut?: boolean | undefined;
|
|
1148
1148
|
readonly credentialsPiOpencode?: boolean | undefined;
|
|
1149
1149
|
readonly captureOwnerMap?: boolean | undefined;
|
|
1150
|
+
readonly workspaceSshUser?: boolean | undefined;
|
|
1151
|
+
readonly personBinding?: boolean | undefined;
|
|
1150
1152
|
} | undefined;
|
|
1151
1153
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
1152
1154
|
readonly getSetupState: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: void | {
|
|
@@ -1171,6 +1173,25 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1171
1173
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
1172
1174
|
};
|
|
1173
1175
|
readonly users: {
|
|
1176
|
+
readonly bindUserPerson: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1177
|
+
readonly params: {
|
|
1178
|
+
readonly userId: string;
|
|
1179
|
+
};
|
|
1180
|
+
readonly payload: {
|
|
1181
|
+
readonly id: string;
|
|
1182
|
+
readonly uid: number;
|
|
1183
|
+
readonly home: string;
|
|
1184
|
+
};
|
|
1185
|
+
readonly responseMode?: Mode;
|
|
1186
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1187
|
+
readonly userId: string;
|
|
1188
|
+
readonly person: {
|
|
1189
|
+
readonly id: string;
|
|
1190
|
+
readonly uid: number;
|
|
1191
|
+
readonly home: string;
|
|
1192
|
+
};
|
|
1193
|
+
readonly created: boolean;
|
|
1194
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError | import("@sealant/api-contracts").UserPersonConflictError), [Mode] extends ["response-only"] ? never : never>;
|
|
1174
1195
|
readonly ensureUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1175
1196
|
readonly payload: {
|
|
1176
1197
|
readonly email: string;
|
|
@@ -1282,6 +1303,18 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1282
1303
|
readonly runId?: string | undefined;
|
|
1283
1304
|
readonly launchId?: string | undefined;
|
|
1284
1305
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
1306
|
+
readonly clearWorkspaceSshUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1307
|
+
readonly params: {
|
|
1308
|
+
readonly workspaceId: string;
|
|
1309
|
+
};
|
|
1310
|
+
readonly query: {
|
|
1311
|
+
readonly ownerUserId?: string | undefined;
|
|
1312
|
+
};
|
|
1313
|
+
readonly responseMode?: Mode;
|
|
1314
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1315
|
+
readonly workspaceId: string;
|
|
1316
|
+
readonly sshUser: null;
|
|
1317
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1285
1318
|
readonly createWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1286
1319
|
readonly headers: {
|
|
1287
1320
|
readonly "idempotency-key"?: string | undefined;
|
|
@@ -1318,6 +1351,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1318
1351
|
readonly ttlSeconds?: number | undefined;
|
|
1319
1352
|
readonly idempotencyKey?: string | undefined;
|
|
1320
1353
|
readonly launchId?: string | undefined;
|
|
1354
|
+
readonly sshAsOwner?: boolean | undefined;
|
|
1321
1355
|
};
|
|
1322
1356
|
readonly responseMode?: Mode;
|
|
1323
1357
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -1340,7 +1374,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1340
1374
|
} | undefined;
|
|
1341
1375
|
readonly replayed?: boolean | undefined;
|
|
1342
1376
|
readonly launchId?: string | undefined;
|
|
1343
|
-
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("@sealant/api-contracts").BudgetExceededError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError), [Mode] extends ["response-only"] ? never : never>;
|
|
1377
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("@sealant/api-contracts").BudgetExceededError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError | import("@sealant/api-contracts").WorkspaceSshOwnerRefusedError), [Mode] extends ["response-only"] ? never : never>;
|
|
1344
1378
|
readonly execWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1345
1379
|
readonly params: {
|
|
1346
1380
|
readonly workspaceId: string;
|
|
@@ -1683,6 +1717,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1683
1717
|
readonly headers: {
|
|
1684
1718
|
readonly "x-sealant-gateway-token"?: string | undefined;
|
|
1685
1719
|
readonly "x-sealant-principal-id"?: string | undefined;
|
|
1720
|
+
readonly "x-sealant-gateway-ssh-user"?: string | undefined;
|
|
1686
1721
|
};
|
|
1687
1722
|
readonly responseMode?: Mode;
|
|
1688
1723
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -1695,6 +1730,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1695
1730
|
readonly status: "failed" | "pending" | "ready" | "running" | "stopped";
|
|
1696
1731
|
readonly endpoint: string;
|
|
1697
1732
|
};
|
|
1733
|
+
readonly sessionUser: string | null;
|
|
1698
1734
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError | import("@sealant/api-contracts").WorkspaceUnauthorizedError), [Mode] extends ["response-only"] ? never : never>;
|
|
1699
1735
|
readonly inspectWorkspaceImage: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1700
1736
|
readonly payload: {
|
|
@@ -3213,6 +3249,8 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3213
3249
|
readonly credentialsPartialPut?: boolean | undefined;
|
|
3214
3250
|
readonly credentialsPiOpencode?: boolean | undefined;
|
|
3215
3251
|
readonly captureOwnerMap?: boolean | undefined;
|
|
3252
|
+
readonly workspaceSshUser?: boolean | undefined;
|
|
3253
|
+
readonly personBinding?: boolean | undefined;
|
|
3216
3254
|
} | undefined;
|
|
3217
3255
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
3218
3256
|
readonly getSetupState: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: void | {
|
|
@@ -3237,6 +3275,25 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3237
3275
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
3238
3276
|
};
|
|
3239
3277
|
readonly users: {
|
|
3278
|
+
readonly bindUserPerson: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3279
|
+
readonly params: {
|
|
3280
|
+
readonly userId: string;
|
|
3281
|
+
};
|
|
3282
|
+
readonly payload: {
|
|
3283
|
+
readonly id: string;
|
|
3284
|
+
readonly uid: number;
|
|
3285
|
+
readonly home: string;
|
|
3286
|
+
};
|
|
3287
|
+
readonly responseMode?: Mode;
|
|
3288
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
3289
|
+
readonly userId: string;
|
|
3290
|
+
readonly person: {
|
|
3291
|
+
readonly id: string;
|
|
3292
|
+
readonly uid: number;
|
|
3293
|
+
readonly home: string;
|
|
3294
|
+
};
|
|
3295
|
+
readonly created: boolean;
|
|
3296
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError | import("@sealant/api-contracts").UserPersonConflictError), [Mode] extends ["response-only"] ? never : never>;
|
|
3240
3297
|
readonly ensureUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3241
3298
|
readonly payload: {
|
|
3242
3299
|
readonly email: string;
|
|
@@ -3348,6 +3405,18 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3348
3405
|
readonly runId?: string | undefined;
|
|
3349
3406
|
readonly launchId?: string | undefined;
|
|
3350
3407
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
3408
|
+
readonly clearWorkspaceSshUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3409
|
+
readonly params: {
|
|
3410
|
+
readonly workspaceId: string;
|
|
3411
|
+
};
|
|
3412
|
+
readonly query: {
|
|
3413
|
+
readonly ownerUserId?: string | undefined;
|
|
3414
|
+
};
|
|
3415
|
+
readonly responseMode?: Mode;
|
|
3416
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
3417
|
+
readonly workspaceId: string;
|
|
3418
|
+
readonly sshUser: null;
|
|
3419
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
3351
3420
|
readonly createWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3352
3421
|
readonly headers: {
|
|
3353
3422
|
readonly "idempotency-key"?: string | undefined;
|
|
@@ -3384,6 +3453,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3384
3453
|
readonly ttlSeconds?: number | undefined;
|
|
3385
3454
|
readonly idempotencyKey?: string | undefined;
|
|
3386
3455
|
readonly launchId?: string | undefined;
|
|
3456
|
+
readonly sshAsOwner?: boolean | undefined;
|
|
3387
3457
|
};
|
|
3388
3458
|
readonly responseMode?: Mode;
|
|
3389
3459
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -3406,7 +3476,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3406
3476
|
} | undefined;
|
|
3407
3477
|
readonly replayed?: boolean | undefined;
|
|
3408
3478
|
readonly launchId?: string | undefined;
|
|
3409
|
-
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("@sealant/api-contracts").BudgetExceededError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError), [Mode] extends ["response-only"] ? never : never>;
|
|
3479
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("@sealant/api-contracts").BudgetExceededError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError | import("@sealant/api-contracts").WorkspaceSshOwnerRefusedError), [Mode] extends ["response-only"] ? never : never>;
|
|
3410
3480
|
readonly execWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3411
3481
|
readonly params: {
|
|
3412
3482
|
readonly workspaceId: string;
|
|
@@ -3749,6 +3819,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3749
3819
|
readonly headers: {
|
|
3750
3820
|
readonly "x-sealant-gateway-token"?: string | undefined;
|
|
3751
3821
|
readonly "x-sealant-principal-id"?: string | undefined;
|
|
3822
|
+
readonly "x-sealant-gateway-ssh-user"?: string | undefined;
|
|
3752
3823
|
};
|
|
3753
3824
|
readonly responseMode?: Mode;
|
|
3754
3825
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
@@ -3761,6 +3832,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
3761
3832
|
readonly status: "failed" | "pending" | "ready" | "running" | "stopped";
|
|
3762
3833
|
readonly endpoint: string;
|
|
3763
3834
|
};
|
|
3835
|
+
readonly sessionUser: string | null;
|
|
3764
3836
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError | import("@sealant/api-contracts").WorkspaceUnauthorizedError), [Mode] extends ["response-only"] ? never : never>;
|
|
3765
3837
|
readonly inspectWorkspaceImage: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
3766
3838
|
readonly payload: {
|
|
@@ -32,6 +32,7 @@ export declare const createWorkspaceOp: (payload: {
|
|
|
32
32
|
readonly ttlSeconds?: number | undefined;
|
|
33
33
|
readonly idempotencyKey?: string | undefined;
|
|
34
34
|
readonly launchId?: string | undefined;
|
|
35
|
+
readonly sshAsOwner?: boolean | undefined;
|
|
35
36
|
}, idempotencyKey?: string | undefined) => Effect.Effect<{
|
|
36
37
|
readonly workspaceId: string;
|
|
37
38
|
readonly name: string;
|
|
@@ -52,7 +53,7 @@ export declare const createWorkspaceOp: (payload: {
|
|
|
52
53
|
} | undefined;
|
|
53
54
|
readonly replayed?: boolean | undefined;
|
|
54
55
|
readonly launchId?: string | undefined;
|
|
55
|
-
}, import("@sealant/api-contracts").BudgetExceededError | import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError, SealantApiClient>;
|
|
56
|
+
}, import("@sealant/api-contracts").BudgetExceededError | import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceDockerServiceUnsupportedError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceRuntimeEnvReferencesUnsupportedError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError | import("@sealant/api-contracts").WorkspaceSshOwnerRefusedError, SealantApiClient>;
|
|
56
57
|
export declare const getWorkspaceOp: (workspaceId: string, ownerUserId?: string | undefined) => Effect.Effect<{
|
|
57
58
|
readonly workspaceId: string;
|
|
58
59
|
readonly name: string;
|
|
@@ -644,6 +645,12 @@ export declare const expireWorkspaceOp: (workspaceId: string, payload: {
|
|
|
644
645
|
readonly workspaceId: string;
|
|
645
646
|
readonly expiresAt: string | null;
|
|
646
647
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
648
|
+
export declare const clearWorkspaceSshUserOp: (workspaceId: string, query: {
|
|
649
|
+
readonly ownerUserId?: string | undefined;
|
|
650
|
+
}) => Effect.Effect<{
|
|
651
|
+
readonly workspaceId: string;
|
|
652
|
+
readonly sshUser: null;
|
|
653
|
+
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
647
654
|
export declare const createRunOp: (payload: {
|
|
648
655
|
readonly workspaceId: string;
|
|
649
656
|
readonly harnessId: string;
|
|
@@ -1062,6 +1069,19 @@ export declare const ensureUserOp: (payload: {
|
|
|
1062
1069
|
readonly createdAt: string;
|
|
1063
1070
|
readonly created: boolean;
|
|
1064
1071
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError, SealantApiClient>;
|
|
1072
|
+
export declare const bindUserPersonOp: (userId: string, payload: {
|
|
1073
|
+
readonly id: string;
|
|
1074
|
+
readonly uid: number;
|
|
1075
|
+
readonly home: string;
|
|
1076
|
+
}) => Effect.Effect<{
|
|
1077
|
+
readonly userId: string;
|
|
1078
|
+
readonly person: {
|
|
1079
|
+
readonly id: string;
|
|
1080
|
+
readonly uid: number;
|
|
1081
|
+
readonly home: string;
|
|
1082
|
+
};
|
|
1083
|
+
readonly created: boolean;
|
|
1084
|
+
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError | import("@sealant/api-contracts").UserPersonConflictError, SealantApiClient>;
|
|
1065
1085
|
export declare const getUserOp: (userId: string) => Effect.Effect<{
|
|
1066
1086
|
readonly userId: string;
|
|
1067
1087
|
readonly email: string;
|
|
@@ -1195,6 +1215,8 @@ export declare const getIndexOp: () => Effect.Effect<{
|
|
|
1195
1215
|
readonly credentialsPartialPut?: boolean | undefined;
|
|
1196
1216
|
readonly credentialsPiOpencode?: boolean | undefined;
|
|
1197
1217
|
readonly captureOwnerMap?: boolean | undefined;
|
|
1218
|
+
readonly workspaceSshUser?: boolean | undefined;
|
|
1219
|
+
readonly personBinding?: boolean | undefined;
|
|
1198
1220
|
} | undefined;
|
|
1199
1221
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1200
1222
|
export declare const getSetupStateOp: () => Effect.Effect<{
|
|
@@ -31,6 +31,7 @@ export const putWorkspaceCredentialsOp = (workspaceId, payload) => Effect.flatMa
|
|
|
31
31
|
export const releaseWorkspaceCredentialsOp = (workspaceId, query) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.releaseWorkspaceCredentials({ params: { workspaceId }, query }));
|
|
32
32
|
export const listWorkspaceCredentialsOp = (workspaceId, query) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.listWorkspaceCredentials({ params: { workspaceId }, query }));
|
|
33
33
|
export const expireWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.expireWorkspace({ params: { workspaceId }, payload }));
|
|
34
|
+
export const clearWorkspaceSshUserOp = (workspaceId, query) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.clearWorkspaceSshUser({ params: { workspaceId }, query }));
|
|
34
35
|
// ---- runs ----
|
|
35
36
|
export const createRunOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.runs.createRun({ payload }));
|
|
36
37
|
const ownerQuery = (ownerUserId) => ownerUserId === undefined ? {} : { ownerUserId };
|
|
@@ -60,6 +61,7 @@ export const closeSessionOp = (sessionId, payload) => Effect.flatMap(SealantApiC
|
|
|
60
61
|
export const createAccessTokenOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.accessTokens.createAccessToken({ payload }));
|
|
61
62
|
// ---- users ----
|
|
62
63
|
export const ensureUserOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.users.ensureUser({ payload }));
|
|
64
|
+
export const bindUserPersonOp = (userId, payload) => Effect.flatMap(SealantApiClient, (client) => client.users.bindUserPerson({ params: { userId }, payload }));
|
|
63
65
|
export const getUserOp = (userId) => Effect.flatMap(SealantApiClient, (client) => client.users.getUser({ params: { userId } }));
|
|
64
66
|
// ---- connected accounts ----
|
|
65
67
|
export const listConnectedAccountsOp = (ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.connectedAccounts.listConnectedAccounts({ query: { ownerUserId } }));
|
package/dist/facade/workspace.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sessionArgvIssue } from "@sealant/api-contracts";
|
|
2
2
|
import { applyDotfiles } from "../effect/apply-dotfiles.js";
|
|
3
3
|
import { execWorkspace } from "../effect/exec-workspace.js";
|
|
4
|
-
import { bindWorkspaceOp, flushWorkspaceCaptureOp, getWorkspaceCaptureStatusOp, createSessionAsUserOp, createSessionOp, expireWorkspaceOp, getSessionOp, getWorkspaceOp, listSessionsOp, replanWorkspaceCaptureOp, recoverWorkspaceOp, restartWorkspaceOp, listWorkspaceCredentialsOp, putWorkspaceCredentialsOp, releaseWorkspaceCredentialsOp, stopWorkspaceOp, } from "../effect/operations.js";
|
|
4
|
+
import { bindWorkspaceOp, flushWorkspaceCaptureOp, getWorkspaceCaptureStatusOp, createSessionAsUserOp, createSessionOp, expireWorkspaceOp, clearWorkspaceSshUserOp, getSessionOp, getWorkspaceOp, listSessionsOp, replanWorkspaceCaptureOp, recoverWorkspaceOp, restartWorkspaceOp, listWorkspaceCredentialsOp, putWorkspaceCredentialsOp, releaseWorkspaceCredentialsOp, stopWorkspaceOp, } from "../effect/operations.js";
|
|
5
5
|
import { SealantApiError, SealantError, SealantNotImplementedError } from "../errors.js";
|
|
6
6
|
import { mapAccountRef } from "../internal/credentials.js";
|
|
7
7
|
import { parseTtlSeconds } from "../internal/duration.js";
|
|
@@ -789,6 +789,9 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
789
789
|
...(ttl === undefined ? {} : { ttlSeconds: ttl === null ? null : parseTtlSeconds(ttl) }),
|
|
790
790
|
}));
|
|
791
791
|
},
|
|
792
|
+
sshAsRoot: async () => {
|
|
793
|
+
await ctx.runtime.run(clearWorkspaceSshUserOp(init.id, { ownerUserId: ctx.config.hostLocal.ownerUserId }));
|
|
794
|
+
},
|
|
792
795
|
forward: (port, options) => openForward(ctx, init.id, port, options),
|
|
793
796
|
};
|
|
794
797
|
return workspace;
|
|
@@ -34,5 +34,6 @@ export declare const buildCreateWorkspaceRequest: (options: CreateOptions, confi
|
|
|
34
34
|
readonly ttlSeconds?: number | undefined;
|
|
35
35
|
readonly idempotencyKey?: string | undefined;
|
|
36
36
|
readonly launchId?: string | undefined;
|
|
37
|
+
readonly sshAsOwner?: boolean | undefined;
|
|
37
38
|
};
|
|
38
39
|
};
|
|
@@ -267,6 +267,7 @@ export const buildCreateWorkspaceRequest = (options, config) => {
|
|
|
267
267
|
...(options.ttl === undefined ? {} : { ttlSeconds: parseTtlSeconds(options.ttl) }),
|
|
268
268
|
...(options.idempotencyKey === undefined ? {} : { idempotencyKey: options.idempotencyKey }),
|
|
269
269
|
...(options.launchId === undefined ? {} : { launchId: options.launchId }),
|
|
270
|
+
...(options.sshAsOwner === true ? { sshAsOwner: true } : {}),
|
|
270
271
|
spec,
|
|
271
272
|
...(secretEnv === undefined ? {} : { secretEnv }),
|
|
272
273
|
// The capture credential is the one secret outside `secretEnv`: sealed and delivered the
|
|
@@ -13,6 +13,8 @@ export declare const toFeatures: (index: {
|
|
|
13
13
|
readonly credentialsPartialPut?: boolean | undefined;
|
|
14
14
|
readonly credentialsPiOpencode?: boolean | undefined;
|
|
15
15
|
readonly captureOwnerMap?: boolean | undefined;
|
|
16
|
+
readonly workspaceSshUser?: boolean | undefined;
|
|
17
|
+
readonly personBinding?: boolean | undefined;
|
|
16
18
|
} | undefined;
|
|
17
19
|
}) => SealantFeatures;
|
|
18
20
|
/**
|
|
@@ -15,6 +15,8 @@ export const toFeatures = (index) => {
|
|
|
15
15
|
credentialsPartialPut: features?.credentialsPartialPut === true,
|
|
16
16
|
credentialsPiOpencode: features?.credentialsPiOpencode === true,
|
|
17
17
|
captureOwnerMap: features?.captureOwnerMap === true,
|
|
18
|
+
workspaceSshUser: features?.workspaceSshUser === true,
|
|
19
|
+
personBinding: features?.personBinding === true,
|
|
18
20
|
};
|
|
19
21
|
};
|
|
20
22
|
/**
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { SdkContext } from "../facade/context.js";
|
|
2
|
+
/**
|
|
3
|
+
* A workspace's SSH user is asked only of a control plane that reports it takes one
|
|
4
|
+
* (`features.workspaceSshUser`): an older one ignores `sshAsOwner` on a create and its gateway
|
|
5
|
+
* would run the sessions as root.
|
|
6
|
+
*/
|
|
7
|
+
export declare const requireSshUser: (ctx: SdkContext) => Promise<void>;
|
|
2
8
|
export declare const requireProcessUser: (ctx: SdkContext, user: string) => Promise<void>;
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { SealantError } from "../errors.js";
|
|
10
10
|
import { readFeatures } from "./features.js";
|
|
11
|
+
/**
|
|
12
|
+
* A workspace's SSH user is asked only of a control plane that reports it takes one
|
|
13
|
+
* (`features.workspaceSshUser`): an older one ignores `sshAsOwner` on a create and its gateway
|
|
14
|
+
* would run the sessions as root.
|
|
15
|
+
*/
|
|
16
|
+
export const requireSshUser = async (ctx) => {
|
|
17
|
+
const supported = await readFeatures(ctx).then((features) => features.workspaceSshUser, () => false);
|
|
18
|
+
if (!supported) {
|
|
19
|
+
throw new SealantError("This control plane cannot run SSH sessions as the owner's Linux user (it does not report the feature, or could not be asked); nothing was sent.", { code: "ssh-user-unsupported" });
|
|
20
|
+
}
|
|
21
|
+
};
|
|
11
22
|
export const requireProcessUser = async (ctx, user) => {
|
|
12
23
|
const supported = await readFeatures(ctx).then((features) => features.processUserRoutes, () => false);
|
|
13
24
|
if (!supported) {
|
package/dist/types.d.ts
CHANGED
|
@@ -883,6 +883,15 @@ export interface CreateOptions {
|
|
|
883
883
|
* the logins are written by the launch itself.
|
|
884
884
|
*/
|
|
885
885
|
readonly credentialsHome?: WorkspaceCredentialsHomeOptions;
|
|
886
|
+
/**
|
|
887
|
+
* The SSH gateway runs this workspace's SSH sessions (VS Code Remote-SSH, an `ssh` shell or
|
|
888
|
+
* command) as its owner's own Linux user: the uid of `credentialsHome`, which this requires
|
|
889
|
+
* (40001–49999, never root). No caller names the user. It need not exist yet; until it does, a
|
|
890
|
+
* session is refused, never run as root. `workspace.sshAsRoot()` sets it back to root. Absent:
|
|
891
|
+
* root. Sent only to a control plane that reports `features().workspaceSshUser`; with another,
|
|
892
|
+
* `create` rejects (`ssh-user-unsupported`) and nothing is created.
|
|
893
|
+
*/
|
|
894
|
+
readonly sshAsOwner?: boolean;
|
|
886
895
|
/**
|
|
887
896
|
* Time-to-live for the workspace, e.g. `"90m"`, `"2h"` (also `"45s"`, `"1d"`). Once it elapses
|
|
888
897
|
* the platform stops the workspace and removes its container. Omitted = the server default TTL
|
|
@@ -1118,6 +1127,12 @@ export interface Workspace {
|
|
|
1118
1127
|
expire(options?: {
|
|
1119
1128
|
readonly in?: string | null;
|
|
1120
1129
|
}): Promise<void>;
|
|
1130
|
+
/**
|
|
1131
|
+
* The SSH gateway runs this workspace's SSH sessions as root from the next session channel on,
|
|
1132
|
+
* open connections included (`DELETE /v1/workspaces/:id/ssh-user`). The only change after
|
|
1133
|
+
* create: a workspace's user is its owner's, set by `sshAsOwner`, never named by a caller.
|
|
1134
|
+
*/
|
|
1135
|
+
sshAsRoot(): Promise<void>;
|
|
1121
1136
|
/**
|
|
1122
1137
|
* Open a raw TCP byte pipe (or a UDP datagram pipe) INSIDE the workspace — the primitive for
|
|
1123
1138
|
* reaching a dev server or database the workspace runs. Protocol-agnostic:
|
|
@@ -1353,6 +1368,10 @@ export interface SealantFeatures {
|
|
|
1353
1368
|
readonly credentialsPiOpencode: boolean;
|
|
1354
1369
|
/** `ownerMap` on a capture source. */
|
|
1355
1370
|
readonly captureOwnerMap: boolean;
|
|
1371
|
+
/** `sshAsOwner` on a create and `workspace.sshAsRoot()`: SSH sessions as the owner's user. */
|
|
1372
|
+
readonly workspaceSshUser: boolean;
|
|
1373
|
+
/** `users.bindPerson()`: a user's person, bound once. */
|
|
1374
|
+
readonly personBinding: boolean;
|
|
1356
1375
|
}
|
|
1357
1376
|
/** A published workspace image. */
|
|
1358
1377
|
export interface WorkspaceImage {
|
|
@@ -2010,9 +2029,29 @@ export interface EnsuredUser extends SealantUser {
|
|
|
2010
2029
|
* Identity rows for products that own their own login. `ensure` is idempotent on email: call it on
|
|
2011
2030
|
* every sign-in and build the per-user client with the returned `userId` as `ownerUserId`.
|
|
2012
2031
|
*/
|
|
2032
|
+
/**
|
|
2033
|
+
* The person a user is (Mend ADR 0016): their id in a capture owner map, their uid (40001–49999)
|
|
2034
|
+
* and their home, under the deployment's homes root.
|
|
2035
|
+
*/
|
|
2036
|
+
export interface UserPerson {
|
|
2037
|
+
readonly id: string;
|
|
2038
|
+
readonly uid: number;
|
|
2039
|
+
readonly home: string;
|
|
2040
|
+
}
|
|
2013
2041
|
export interface UsersNamespace {
|
|
2014
2042
|
ensure(options: EnsureUserOptions): Promise<EnsuredUser>;
|
|
2015
2043
|
get(userId: string): Promise<SealantUser>;
|
|
2044
|
+
/**
|
|
2045
|
+
* Binds the user to a person, once (what `create({ sshAsOwner })` checks a create against). The
|
|
2046
|
+
* same values again answer `created: false`; another person for the user, or a person id or uid
|
|
2047
|
+
* another user holds, rejects (409, `reason` `person-binding-differs` or `person-taken`) and
|
|
2048
|
+
* changes nothing. Needs a service key and `features().personBinding`.
|
|
2049
|
+
*/
|
|
2050
|
+
bindPerson(userId: string, person: UserPerson): Promise<{
|
|
2051
|
+
readonly userId: string;
|
|
2052
|
+
readonly person: UserPerson;
|
|
2053
|
+
readonly created: boolean;
|
|
2054
|
+
}>;
|
|
2016
2055
|
}
|
|
2017
2056
|
export type ConnectedAccountProvider = "claude" | "codex" | "github";
|
|
2018
2057
|
export type ConnectedAccountStatus = "active" | "invalid" | "archived";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/sdk-next",
|
|
3
|
-
"version": "0.39.0-next.
|
|
3
|
+
"version": "0.39.0-next.714",
|
|
4
4
|
"description": "The fluent public SDK for Sealant — create a workspace, run a harness, replay the record.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@sealant/api-contracts": "npm:@sealant/api-contracts-next@0.39.0-next.
|
|
29
|
+
"@sealant/api-contracts": "npm:@sealant/api-contracts-next@0.39.0-next.714"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"effect": ">=4.0.0-beta.85 <5"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "6da21a94e3f8650df5cbdb53626f420981cd1831",
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
37
37
|
}
|