@sealant/sdk-next 0.40.0-next.763 → 0.40.0-next.764

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/dist/client.js CHANGED
@@ -7,7 +7,7 @@ import { makeWorkspace, registerHarnessExecutors, toRuntimeInfo, toWorkspaceImag
7
7
  import { buildCreateWorkspaceRequest } from "./internal/blueprint.js";
8
8
  import { resolveInternalConfig } from "./internal/config.js";
9
9
  import { parseTtlSeconds } from "./internal/duration.js";
10
- import { readFeatures, requireConnectedAccountDefaults } from "./internal/features.js";
10
+ import { readFeatures, requireConnectedAccountDefaults, requireConnectedAccountLoginClass, } from "./internal/features.js";
11
11
  import { imageSpecKey } from "./internal/image-key.js";
12
12
  import { buildInferenceRespondRequest, mapInferenceResponse } from "./internal/inference.js";
13
13
  import { requireSshUser } from "./internal/process-user.js";
@@ -35,6 +35,7 @@ const mapConnectedAccount = (wire) => ({
35
35
  credential: wire.credential,
36
36
  isDefault: wire.isDefault ?? wire.name === "default",
37
37
  ...(wire.credentialRevision === undefined ? {} : { credentialRevision: wire.credentialRevision }),
38
+ ...(wire.login === undefined ? {} : { login: wire.login }),
38
39
  });
39
40
  // Wire the run-execution implementations into the Workspace facade (the injection point exists to
40
41
  // break the workspace <-> run-harness import cycle; the client is the composition root).
@@ -244,10 +245,20 @@ export class Sealant {
244
245
  const wire = await this.#runtime.run(listConnectedAccountsOp(this.#ctx.config.hostLocal.ownerUserId));
245
246
  return wire.items.map(mapConnectedAccount);
246
247
  },
248
+ listWithHistory: async () => {
249
+ const wire = await this.#runtime.run(listConnectedAccountsOp(this.#ctx.config.hostLocal.ownerUserId));
250
+ return {
251
+ accounts: wire.items.map(mapConnectedAccount),
252
+ ...(wire.hasApiKeyHistory === undefined ? {} : { hasApiKeyHistory: wire.hasApiKeyHistory }),
253
+ };
254
+ },
247
255
  connect: async (options) => {
248
256
  if (options.accountId !== undefined || options.makeDefault !== undefined) {
249
257
  await requireConnectedAccountDefaults(this.#ctx);
250
258
  }
259
+ if (options.login !== undefined) {
260
+ await requireConnectedAccountLoginClass(this.#ctx);
261
+ }
251
262
  const wire = await this.#runtime.run(createConnectedAccountOp({
252
263
  ownerUserId: this.#ctx.config.hostLocal.ownerUserId,
253
264
  provider: options.provider,
@@ -255,6 +266,7 @@ export class Sealant {
255
266
  ...(options.name === undefined ? {} : { name: options.name }),
256
267
  ...(options.accountId === undefined ? {} : { accountId: options.accountId }),
257
268
  ...(options.makeDefault === undefined ? {} : { makeDefault: options.makeDefault }),
269
+ ...(options.login === undefined ? {} : { login: options.login }),
258
270
  }));
259
271
  return mapConnectedAccount(wire);
260
272
  },
@@ -76,6 +76,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
76
76
  }>;
77
77
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
78
78
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
79
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
80
+ readonly kind: import("effect/Schema").Literal<"subscription">;
81
+ }>, import("effect/Schema").Struct<{
82
+ readonly kind: import("effect/Schema").Literal<"api-key">;
83
+ readonly suffix: import("effect/Schema").String;
84
+ }>]>>;
79
85
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
80
86
  readonly createConnectedAccount: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"createConnectedAccount", "POST", "/v1/connected-accounts/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
81
87
  readonly ownerUserId: import("effect/Schema").String;
@@ -83,6 +89,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
83
89
  readonly name: import("effect/Schema").optional<import("effect/Schema").String>;
84
90
  readonly accountId: import("effect/Schema").optional<import("effect/Schema").String>;
85
91
  readonly makeDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
92
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["subscription", "api-key"]>>;
86
93
  readonly secret: import("effect/Schema").String;
87
94
  }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
88
95
  readonly connectedAccountId: import("effect/Schema").String;
@@ -104,6 +111,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
104
111
  }>;
105
112
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
106
113
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
114
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
115
+ readonly kind: import("effect/Schema").Literal<"subscription">;
116
+ }>, import("effect/Schema").Struct<{
117
+ readonly kind: import("effect/Schema").Literal<"api-key">;
118
+ readonly suffix: import("effect/Schema").String;
119
+ }>]>>;
107
120
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountBadRequestError | typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountConflictError | typeof import("@sealant/api-contracts").ConnectedAccountServiceUnavailableError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
108
121
  readonly listConnectedAccounts: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"listConnectedAccounts", "GET", "/v1/connected-accounts/", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
109
122
  readonly ownerUserId: import("effect/Schema").String;
@@ -128,7 +141,14 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
128
141
  }>;
129
142
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
130
143
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
131
- }>>;
144
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
145
+ readonly kind: import("effect/Schema").Literal<"subscription">;
146
+ }>, import("effect/Schema").Struct<{
147
+ readonly kind: import("effect/Schema").Literal<"api-key">;
148
+ readonly suffix: import("effect/Schema").String;
149
+ }>]>>;
150
+ }>>;
151
+ readonly hasApiKeyHistory: import("effect/Schema").optional<import("effect/Schema").Boolean>;
132
152
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
133
153
  readonly markConnectedAccountInvalid: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"markConnectedAccountInvalid", "POST", "/v1/connected-accounts/:connectedAccountId/mark-invalid", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
134
154
  readonly connectedAccountId: import("effect/Schema").String;
@@ -155,6 +175,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
155
175
  }>;
156
176
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
157
177
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
178
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
179
+ readonly kind: import("effect/Schema").Literal<"subscription">;
180
+ }>, import("effect/Schema").Struct<{
181
+ readonly kind: import("effect/Schema").Literal<"api-key">;
182
+ readonly suffix: import("effect/Schema").String;
183
+ }>]>>;
158
184
  readonly outcome: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["marked", "superseded"]>>;
159
185
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
160
186
  readonly setConnectedAccountDefault: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"setConnectedAccountDefault", "PUT", "/v1/connected-accounts/defaults/:provider", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
@@ -182,6 +208,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
182
208
  }>;
183
209
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
184
210
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
211
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
212
+ readonly kind: import("effect/Schema").Literal<"subscription">;
213
+ }>, import("effect/Schema").Struct<{
214
+ readonly kind: import("effect/Schema").Literal<"api-key">;
215
+ readonly suffix: import("effect/Schema").String;
216
+ }>]>>;
185
217
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountConflictError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
186
218
  };
187
219
  readonly github: {
@@ -381,6 +413,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
381
413
  }>;
382
414
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
383
415
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
416
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
417
+ readonly kind: import("effect/Schema").Literal<"subscription">;
418
+ }>, import("effect/Schema").Struct<{
419
+ readonly kind: import("effect/Schema").Literal<"api-key">;
420
+ readonly suffix: import("effect/Schema").String;
421
+ }>]>>;
384
422
  }>;
385
423
  }>>;
386
424
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ProfileNotFoundError | typeof import("@sealant/api-contracts").ProfileInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -430,6 +468,12 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
430
468
  }>;
431
469
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
432
470
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
471
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
472
+ readonly kind: import("effect/Schema").Literal<"subscription">;
473
+ }>, import("effect/Schema").Struct<{
474
+ readonly kind: import("effect/Schema").Literal<"api-key">;
475
+ readonly suffix: import("effect/Schema").String;
476
+ }>]>>;
433
477
  }>;
434
478
  }>>;
435
479
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ProfileBadRequestError | typeof import("@sealant/api-contracts").ProfileNotFoundError | typeof import("@sealant/api-contracts").ProfileConflictError | typeof import("@sealant/api-contracts").ProfileInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -985,6 +1029,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
985
1029
  readonly personBinding: import("effect/Schema").optional<import("effect/Schema").Boolean>;
986
1030
  readonly sshKeyRemovalEndsConnections: import("effect/Schema").optional<import("effect/Schema").Boolean>;
987
1031
  readonly connectedAccountDefaults: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1032
+ readonly connectedAccountLoginClass: import("effect/Schema").optional<import("effect/Schema").Boolean>;
988
1033
  readonly kubernetesPersonLayout: import("effect/Schema").optional<import("effect/Schema").Boolean>;
989
1034
  }>>;
990
1035
  }>>, never, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -1895,6 +1940,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
1895
1940
  }>;
1896
1941
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1897
1942
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
1943
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
1944
+ readonly kind: import("effect/Schema").Literal<"subscription">;
1945
+ }>, import("effect/Schema").Struct<{
1946
+ readonly kind: import("effect/Schema").Literal<"api-key">;
1947
+ readonly suffix: import("effect/Schema").String;
1948
+ }>]>>;
1898
1949
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
1899
1950
  readonly createConnectedAccount: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"createConnectedAccount", "POST", "/v1/connected-accounts/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
1900
1951
  readonly ownerUserId: import("effect/Schema").String;
@@ -1902,6 +1953,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
1902
1953
  readonly name: import("effect/Schema").optional<import("effect/Schema").String>;
1903
1954
  readonly accountId: import("effect/Schema").optional<import("effect/Schema").String>;
1904
1955
  readonly makeDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1956
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["subscription", "api-key"]>>;
1905
1957
  readonly secret: import("effect/Schema").String;
1906
1958
  }>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
1907
1959
  readonly connectedAccountId: import("effect/Schema").String;
@@ -1923,6 +1975,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
1923
1975
  }>;
1924
1976
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1925
1977
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
1978
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
1979
+ readonly kind: import("effect/Schema").Literal<"subscription">;
1980
+ }>, import("effect/Schema").Struct<{
1981
+ readonly kind: import("effect/Schema").Literal<"api-key">;
1982
+ readonly suffix: import("effect/Schema").String;
1983
+ }>]>>;
1926
1984
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountBadRequestError | typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountConflictError | typeof import("@sealant/api-contracts").ConnectedAccountServiceUnavailableError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
1927
1985
  readonly listConnectedAccounts: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"listConnectedAccounts", "GET", "/v1/connected-accounts/", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
1928
1986
  readonly ownerUserId: import("effect/Schema").String;
@@ -1947,7 +2005,14 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
1947
2005
  }>;
1948
2006
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1949
2007
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
1950
- }>>;
2008
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
2009
+ readonly kind: import("effect/Schema").Literal<"subscription">;
2010
+ }>, import("effect/Schema").Struct<{
2011
+ readonly kind: import("effect/Schema").Literal<"api-key">;
2012
+ readonly suffix: import("effect/Schema").String;
2013
+ }>]>>;
2014
+ }>>;
2015
+ readonly hasApiKeyHistory: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1951
2016
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
1952
2017
  readonly markConnectedAccountInvalid: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"markConnectedAccountInvalid", "POST", "/v1/connected-accounts/:connectedAccountId/mark-invalid", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
1953
2018
  readonly connectedAccountId: import("effect/Schema").String;
@@ -1974,6 +2039,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
1974
2039
  }>;
1975
2040
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
1976
2041
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
2042
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
2043
+ readonly kind: import("effect/Schema").Literal<"subscription">;
2044
+ }>, import("effect/Schema").Struct<{
2045
+ readonly kind: import("effect/Schema").Literal<"api-key">;
2046
+ readonly suffix: import("effect/Schema").String;
2047
+ }>]>>;
1977
2048
  readonly outcome: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["marked", "superseded"]>>;
1978
2049
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
1979
2050
  readonly setConnectedAccountDefault: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"setConnectedAccountDefault", "PUT", "/v1/connected-accounts/defaults/:provider", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
@@ -2001,6 +2072,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
2001
2072
  }>;
2002
2073
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2003
2074
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
2075
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
2076
+ readonly kind: import("effect/Schema").Literal<"subscription">;
2077
+ }>, import("effect/Schema").Struct<{
2078
+ readonly kind: import("effect/Schema").Literal<"api-key">;
2079
+ readonly suffix: import("effect/Schema").String;
2080
+ }>]>>;
2004
2081
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ConnectedAccountNotFoundError | typeof import("@sealant/api-contracts").ConnectedAccountConflictError | typeof import("@sealant/api-contracts").ConnectedAccountInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
2005
2082
  };
2006
2083
  readonly github: {
@@ -2200,6 +2277,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
2200
2277
  }>;
2201
2278
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2202
2279
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
2280
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
2281
+ readonly kind: import("effect/Schema").Literal<"subscription">;
2282
+ }>, import("effect/Schema").Struct<{
2283
+ readonly kind: import("effect/Schema").Literal<"api-key">;
2284
+ readonly suffix: import("effect/Schema").String;
2285
+ }>]>>;
2203
2286
  }>;
2204
2287
  }>>;
2205
2288
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ProfileNotFoundError | typeof import("@sealant/api-contracts").ProfileInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -2249,6 +2332,12 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
2249
2332
  }>;
2250
2333
  readonly isDefault: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2251
2334
  readonly credentialRevision: import("effect/Schema").optional<import("effect/Schema").Int>;
2335
+ readonly login: import("effect/Schema").optional<import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
2336
+ readonly kind: import("effect/Schema").Literal<"subscription">;
2337
+ }>, import("effect/Schema").Struct<{
2338
+ readonly kind: import("effect/Schema").Literal<"api-key">;
2339
+ readonly suffix: import("effect/Schema").String;
2340
+ }>]>>;
2252
2341
  }>;
2253
2342
  }>>;
2254
2343
  }>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ProfileBadRequestError | typeof import("@sealant/api-contracts").ProfileNotFoundError | typeof import("@sealant/api-contracts").ProfileConflictError | typeof import("@sealant/api-contracts").ProfileInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -2804,6 +2893,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
2804
2893
  readonly personBinding: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2805
2894
  readonly sshKeyRemovalEndsConnections: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2806
2895
  readonly connectedAccountDefaults: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2896
+ readonly connectedAccountLoginClass: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2807
2897
  readonly kubernetesPersonLayout: import("effect/Schema").optional<import("effect/Schema").Boolean>;
2808
2898
  }>>;
2809
2899
  }>>, never, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
@@ -1111,7 +1111,14 @@ export declare const listConnectedAccountsOp: (ownerUserId: string) => Effect.Ef
1111
1111
  };
1112
1112
  readonly isDefault?: boolean | undefined;
1113
1113
  readonly credentialRevision?: number | undefined;
1114
+ readonly login?: {
1115
+ readonly kind: "subscription";
1116
+ } | {
1117
+ readonly kind: "api-key";
1118
+ readonly suffix: string;
1119
+ } | undefined;
1114
1120
  }[];
1121
+ readonly hasApiKeyHistory?: boolean | undefined;
1115
1122
  }, import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
1116
1123
  export declare const createConnectedAccountOp: (payload: {
1117
1124
  readonly ownerUserId: string;
@@ -1119,6 +1126,7 @@ export declare const createConnectedAccountOp: (payload: {
1119
1126
  readonly name?: string | undefined;
1120
1127
  readonly accountId?: string | undefined;
1121
1128
  readonly makeDefault?: boolean | undefined;
1129
+ readonly login?: "api-key" | "subscription" | undefined;
1122
1130
  readonly secret: string;
1123
1131
  }) => Effect.Effect<{
1124
1132
  readonly connectedAccountId: string;
@@ -1142,6 +1150,12 @@ export declare const createConnectedAccountOp: (payload: {
1142
1150
  };
1143
1151
  readonly isDefault?: boolean | undefined;
1144
1152
  readonly credentialRevision?: number | undefined;
1153
+ readonly login?: {
1154
+ readonly kind: "subscription";
1155
+ } | {
1156
+ readonly kind: "api-key";
1157
+ readonly suffix: string;
1158
+ } | undefined;
1145
1159
  }, import("@sealant/api-contracts").ConnectedAccountBadRequestError | import("@sealant/api-contracts").ConnectedAccountConflictError | import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("@sealant/api-contracts").ConnectedAccountServiceUnavailableError | import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
1146
1160
  export declare const archiveConnectedAccountOp: (connectedAccountId: string, ownerUserId: string) => Effect.Effect<{
1147
1161
  readonly connectedAccountId: string;
@@ -1165,6 +1179,12 @@ export declare const archiveConnectedAccountOp: (connectedAccountId: string, own
1165
1179
  };
1166
1180
  readonly isDefault?: boolean | undefined;
1167
1181
  readonly credentialRevision?: number | undefined;
1182
+ readonly login?: {
1183
+ readonly kind: "subscription";
1184
+ } | {
1185
+ readonly kind: "api-key";
1186
+ readonly suffix: string;
1187
+ } | undefined;
1168
1188
  }, import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
1169
1189
  export declare const setConnectedAccountDefaultOp: (provider: "claude" | "codex" | "github", payload: {
1170
1190
  readonly ownerUserId: string;
@@ -1191,6 +1211,12 @@ export declare const setConnectedAccountDefaultOp: (provider: "claude" | "codex"
1191
1211
  };
1192
1212
  readonly isDefault?: boolean | undefined;
1193
1213
  readonly credentialRevision?: number | undefined;
1214
+ readonly login?: {
1215
+ readonly kind: "subscription";
1216
+ } | {
1217
+ readonly kind: "api-key";
1218
+ readonly suffix: string;
1219
+ } | undefined;
1194
1220
  }, import("@sealant/api-contracts").ConnectedAccountConflictError | import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
1195
1221
  export declare const markConnectedAccountInvalidOp: (connectedAccountId: string, payload: {
1196
1222
  readonly ownerUserId: string;
@@ -1217,6 +1243,12 @@ export declare const markConnectedAccountInvalidOp: (connectedAccountId: string,
1217
1243
  };
1218
1244
  readonly isDefault?: boolean | undefined;
1219
1245
  readonly credentialRevision?: number | undefined;
1246
+ readonly login?: {
1247
+ readonly kind: "subscription";
1248
+ } | {
1249
+ readonly kind: "api-key";
1250
+ readonly suffix: string;
1251
+ } | undefined;
1220
1252
  readonly outcome?: "marked" | "superseded" | undefined;
1221
1253
  }, import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
1222
1254
  export declare const inferenceRespondOp: (payload: {
@@ -1280,6 +1312,7 @@ export declare const getIndexOp: () => Effect.Effect<{
1280
1312
  readonly personBinding?: boolean | undefined;
1281
1313
  readonly sshKeyRemovalEndsConnections?: boolean | undefined;
1282
1314
  readonly connectedAccountDefaults?: boolean | undefined;
1315
+ readonly connectedAccountLoginClass?: boolean | undefined;
1283
1316
  readonly kubernetesPersonLayout?: boolean | undefined;
1284
1317
  } | undefined;
1285
1318
  }, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError, SealantApiClient>;
@@ -17,6 +17,7 @@ export declare const toFeatures: (index: {
17
17
  readonly personBinding?: boolean | undefined;
18
18
  readonly sshKeyRemovalEndsConnections?: boolean | undefined;
19
19
  readonly connectedAccountDefaults?: boolean | undefined;
20
+ readonly connectedAccountLoginClass?: boolean | undefined;
20
21
  readonly kubernetesPersonLayout?: boolean | undefined;
21
22
  } | undefined;
22
23
  }) => SealantFeatures;
@@ -26,3 +27,4 @@ export declare const toFeatures: (index: {
26
27
  */
27
28
  export declare const readFeatures: (ctx: SdkContext) => Promise<SealantFeatures>;
28
29
  export declare const requireConnectedAccountDefaults: (ctx: SdkContext) => Promise<void>;
30
+ export declare const requireConnectedAccountLoginClass: (ctx: SdkContext) => Promise<void>;
@@ -21,6 +21,7 @@ export const toFeatures = (index) => {
21
21
  personBinding: features?.personBinding === true,
22
22
  sshKeyRemovalEndsConnections: features?.sshKeyRemovalEndsConnections === true,
23
23
  connectedAccountDefaults: features?.connectedAccountDefaults === true,
24
+ connectedAccountLoginClass: features?.connectedAccountLoginClass === true,
24
25
  kubernetesPersonLayout: features?.kubernetesPersonLayout === true,
25
26
  };
26
27
  };
@@ -50,3 +51,9 @@ export const requireConnectedAccountDefaults = async (ctx) => {
50
51
  throw new SealantError("This control plane cannot choose a default connected account or target one by id (it does not report the feature, or could not be asked); nothing was sent.", { code: "connected-account-defaults-unsupported" });
51
52
  }
52
53
  };
54
+ export const requireConnectedAccountLoginClass = async (ctx) => {
55
+ const supported = await readFeatures(ctx).then((features) => features.connectedAccountLoginClass, () => false);
56
+ if (!supported) {
57
+ throw new SealantError("This control plane cannot check a connect's login class (it does not report the feature, or could not be asked), and would store the secret whatever it is; nothing was sent.", { code: "connected-account-login-class-unsupported" });
58
+ }
59
+ };
package/dist/types.d.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  * `SealantNotImplementedError` at runtime, see `./errors.js`).
16
16
  */
17
17
  import type { ReadableStream as NodeReadableStream, WritableStream as NodeWritableStream } from "node:stream/web";
18
- import type { ForwardBinding, ForwardResetReason } from "@sealant/api-contracts";
18
+ import type { ConnectedAccountLogin, ConnectedAccountLoginClass, ForwardBinding, ForwardResetReason } from "@sealant/api-contracts";
19
19
  /**
20
20
  * Public client configuration. Intentionally minimal: a base URL and an API key. Host-local
21
21
  * concerns required by the current slice (owner identity, registry, direct database access) live in
@@ -1186,7 +1186,7 @@ export interface WorkspaceCredentials {
1186
1186
  * (missing, not a directory, reached through a symbolic link, or a login directory linking out
1187
1187
  * of it), `home-busy` (another write into it is still running: retry), `workspace-not-running`,
1188
1188
  * `connected-account-invalid`, `connected-account-unsupported` (a Codex account named for pi or
1189
- * opencode that is not a ChatGPT login); with
1189
+ * opencode that is not a ChatGPT login, or a Claude API key, which cannot be placed yet); with
1190
1190
  * `WorkspaceNotFoundError` for an account `onBehalfOf` cannot name; with
1191
1191
  * `WorkspaceBadGatewayError` when the executor did not confirm the write. The body code is
1192
1192
  * `SealantApiError.reason`; a refused account is `reason` `connected-account-missing` (404) or
@@ -1413,6 +1413,12 @@ export interface SealantFeatures {
1413
1413
  * `default`.
1414
1414
  */
1415
1415
  readonly connectedAccountDefaults: boolean;
1416
+ /**
1417
+ * `login` on `connect()` (a secret of the other login class is refused), Claude and Codex API
1418
+ * keys beside a subscription, `ConnectedAccount.login`, and `hasApiKeyHistory` from
1419
+ * `connectedAccounts.listWithHistory()`.
1420
+ */
1421
+ readonly connectedAccountLoginClass: boolean;
1416
1422
  /**
1417
1423
  * `ownerMap` is taken on Kubernetes (runc): each person's `sudo` works in the Pod, and images the
1418
1424
  * cluster builds record the probe a per-person launch checks. From an older control plane a
@@ -2177,12 +2183,16 @@ export interface ConnectedAccountCredential {
2177
2183
  readonly lastRefreshAt: string | null;
2178
2184
  readonly lastRefreshOutcome: "refreshed" | "fresh" | "failed" | null;
2179
2185
  }
2186
+ export type { ConnectedAccountLogin, ConnectedAccountLoginClass };
2180
2187
  export interface ConnectedAccount {
2181
2188
  readonly connectedAccountId: string;
2182
2189
  readonly ownerUserId: string;
2183
2190
  readonly provider: ConnectedAccountProvider;
2184
2191
  readonly name: string;
2185
- /** Provider-shaped payload kind: oauth-token | credentials-json | auth-json | gh-cli-token. */
2192
+ /**
2193
+ * Provider-shaped payload kind: oauth-token | credentials-json | auth-json | gh-cli-token |
2194
+ * api-key.
2195
+ */
2186
2196
  readonly kind: string;
2187
2197
  readonly status: ConnectedAccountStatus;
2188
2198
  /** Non-secret display data (token suffix, codex account email, github login + scopes). */
@@ -2202,14 +2212,31 @@ export interface ConnectedAccount {
2202
2212
  * from a control plane without `connectedAccountDefaults`.
2203
2213
  */
2204
2214
  readonly credentialRevision?: number;
2215
+ /** Claude and Codex only: the account's login class. Absent from an older control plane. */
2216
+ readonly login?: ConnectedAccountLogin;
2217
+ }
2218
+ /** The owner's accounts, and whether they ever connected an API key. */
2219
+ export interface ConnectedAccountList {
2220
+ readonly accounts: readonly ConnectedAccount[];
2221
+ /**
2222
+ * Whether the owner ever connected an API key, archived ones included. Absent from a control
2223
+ * plane that does not report it.
2224
+ */
2225
+ readonly hasApiKeyHistory?: boolean;
2205
2226
  }
2206
2227
  interface ConnectConnectedAccountBase {
2207
2228
  readonly provider: ConnectedAccountProvider;
2208
2229
  /**
2209
- * Provider-shaped plaintext, passed through and sealed server-side: a Claude setup token or
2210
- * verbatim `.credentials.json`, verbatim Codex `auth.json`, or a GitHub token. Never logged.
2230
+ * Provider-shaped plaintext, passed through and sealed server-side: a Claude setup token, API key
2231
+ * or verbatim `.credentials.json`, a verbatim Codex `auth.json` or an OpenAI API key, or a GitHub
2232
+ * token. Never logged.
2211
2233
  */
2212
2234
  readonly secret: string;
2235
+ /**
2236
+ * Claude and Codex: the login class `secret` must be. A secret of the other class is refused
2237
+ * before anything is stored. Needs `features().connectedAccountLoginClass`.
2238
+ */
2239
+ readonly login?: ConnectedAccountLoginClass;
2213
2240
  /**
2214
2241
  * Make the connected account the owner's default for the provider. A first account is the default
2215
2242
  * without it. Needs `features().connectedAccountDefaults`.
@@ -2220,8 +2247,10 @@ interface ConnectConnectedAccountBase {
2220
2247
  * Which account a connect writes. A person's first account for a provider is named `default`
2221
2248
  * whatever `name` says. After that, `name` replaces the account of that name or makes a new one,
2222
2249
  * and `name: "default"` replaces the chosen default. With neither `name` nor `accountId` (or
2223
- * `default` while none is chosen), an only account is replaced, and with several the call fails
2224
- * with `reason` `connected-account-ambiguous` and the candidates in `candidateAccountIds`.
2250
+ * `default` while none is chosen), the only account of the secret's login class is replaced, so a
2251
+ * key never replaces a subscription; with none of that class a new one is made (named `api-key` or
2252
+ * `subscription`), and with several the call fails with `reason` `connected-account-ambiguous` and
2253
+ * the candidates in `candidateAccountIds`.
2225
2254
  */
2226
2255
  export type ConnectConnectedAccountOptions = ConnectConnectedAccountBase & ({
2227
2256
  readonly name?: string;
@@ -2254,6 +2283,8 @@ export interface MarkConnectedAccountInvalidResult {
2254
2283
  */
2255
2284
  export interface ConnectedAccountsNamespace {
2256
2285
  list(): Promise<readonly ConnectedAccount[]>;
2286
+ /** The same accounts as `list`, with whether the owner ever connected an API key. */
2287
+ listWithHistory(): Promise<ConnectedAccountList>;
2257
2288
  connect(options: ConnectConnectedAccountOptions): Promise<ConnectedAccount>;
2258
2289
  /**
2259
2290
  * Soft-archives the account; uniform not-found for "does not exist" and "not yours". Archiving
@@ -2311,4 +2342,3 @@ export interface SshKeysNamespace {
2311
2342
  /** Archives the key; the gateway stops resolving it. */
2312
2343
  remove(sshKeyId: string): Promise<SshKey>;
2313
2344
  }
2314
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealant/sdk-next",
3
- "version": "0.40.0-next.763",
3
+ "version": "0.40.0-next.764",
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.40.0-next.763"
29
+ "@sealant/api-contracts": "npm:@sealant/api-contracts-next@0.40.0-next.764"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "effect": "^4.0.5"
33
33
  },
34
- "gitHead": "c741e10743b2c553b526f93565c256fe8fa4bd8b",
34
+ "gitHead": "4d306e5cd66c40f162f7346370edd82930c1bc02",
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  }