@sealant/sdk-next 0.40.0-next.769 → 0.40.0-next.771
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.d.ts +6 -0
- package/dist/client.js +7 -0
- package/dist/effect/api-client.d.ts +204 -2
- package/dist/effect/operations.d.ts +100 -0
- package/dist/effect/operations.js +17 -0
- package/dist/index.d.ts +1 -0
- package/dist/scopes.d.ts +123 -0
- package/dist/scopes.js +48 -0
- package/package.json +3 -3
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { type ScopesNamespace } from "./scopes.js";
|
|
1
2
|
import type { AccessTokensNamespace, ConnectedAccountsNamespace, CreateOptions, InferenceNamespace, ListOptions, Run, SealantFeatures, SshKeysNamespace, Workspace, WorkspaceCreateState, WorkspaceImageInspection, WorkspaceSshNamespace, SealantConfig, UsersNamespace } from "./types.js";
|
|
2
3
|
export declare class Sealant {
|
|
3
4
|
#private;
|
|
5
|
+
/**
|
|
6
|
+
* Owners that are projects, not people: ensure one per project and name its members. With a
|
|
7
|
+
* service key; `actAs` gives a client for one scope that cannot reach a credential or a harness.
|
|
8
|
+
*/
|
|
9
|
+
readonly scopes: ScopesNamespace;
|
|
4
10
|
constructor(config: SealantConfig);
|
|
5
11
|
/** The configured control-plane base URL. */
|
|
6
12
|
get baseUrl(): string;
|
package/dist/client.js
CHANGED
|
@@ -12,6 +12,7 @@ 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";
|
|
14
14
|
import { mapSshKey, mapWorkspaceSshInfo } from "./internal/ssh.js";
|
|
15
|
+
import { makeScopes } from "./scopes.js";
|
|
15
16
|
/** An idempotent create's state as the SDK reports it (an unknown wire state fails closed). */
|
|
16
17
|
const toCreateState = (wire) => ({
|
|
17
18
|
idempotencyKey: wire.idempotencyKey,
|
|
@@ -44,6 +45,11 @@ export class Sealant {
|
|
|
44
45
|
#config;
|
|
45
46
|
#runtime;
|
|
46
47
|
#ctx;
|
|
48
|
+
/**
|
|
49
|
+
* Owners that are projects, not people: ensure one per project and name its members. With a
|
|
50
|
+
* service key; `actAs` gives a client for one scope that cannot reach a credential or a harness.
|
|
51
|
+
*/
|
|
52
|
+
scopes;
|
|
47
53
|
constructor(config) {
|
|
48
54
|
if (config.baseUrl.trim().length === 0) {
|
|
49
55
|
throw new SealantError("Sealant requires a non-empty `baseUrl`.", { code: "invalid_config" });
|
|
@@ -52,6 +58,7 @@ export class Sealant {
|
|
|
52
58
|
this.#config = config;
|
|
53
59
|
this.#runtime = makeSdkRuntime(internalConfig);
|
|
54
60
|
this.#ctx = { runtime: this.#runtime, config: internalConfig };
|
|
61
|
+
this.scopes = makeScopes(this.#runtime);
|
|
55
62
|
}
|
|
56
63
|
/** The configured control-plane base URL. */
|
|
57
64
|
get baseUrl() {
|
|
@@ -527,12 +527,13 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
527
527
|
readonly resourceDomains: {
|
|
528
528
|
readonly ensureResourceDomain: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"ensureResourceDomain", "POST", "/v1/resource-domains/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
529
529
|
readonly key: import("effect/Schema").String;
|
|
530
|
+
readonly budget: import("effect/Schema").optional<import("effect/Schema").Struct<Record<"cpuMillicores" | "memoryBytes" | "storageBytes", import("effect/Schema").Int>>>;
|
|
530
531
|
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
531
532
|
readonly resourceDomainId: import("effect/Schema").String;
|
|
532
533
|
readonly key: import("effect/Schema").String;
|
|
533
534
|
readonly createdAt: import("effect/Schema").String;
|
|
534
535
|
readonly created: import("effect/Schema").Boolean;
|
|
535
|
-
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
536
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainBudgetDiffersError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
536
537
|
readonly getResourceDomain: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomain", "GET", "/v1/resource-domains/:resourceDomainId", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
537
538
|
readonly resourceDomainId: import("effect/Schema").String;
|
|
538
539
|
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
@@ -540,6 +541,106 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
540
541
|
readonly key: import("effect/Schema").String;
|
|
541
542
|
readonly createdAt: import("effect/Schema").String;
|
|
542
543
|
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
544
|
+
readonly getResourceDomainBudget: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomainBudget", "GET", "/v1/resource-domains/:resourceDomainId/budget", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
545
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
546
|
+
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
547
|
+
readonly revision: import("effect/Schema").Int;
|
|
548
|
+
readonly storageBytes: import("effect/Schema").Struct<{
|
|
549
|
+
readonly limit: import("effect/Schema").Int;
|
|
550
|
+
readonly used: import("effect/Schema").Int;
|
|
551
|
+
readonly reserved: import("effect/Schema").Int;
|
|
552
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
553
|
+
readonly archived: import("effect/Schema").Int;
|
|
554
|
+
readonly protection: import("effect/Schema").Int;
|
|
555
|
+
}>;
|
|
556
|
+
readonly cpuMillicores: import("effect/Schema").Struct<{
|
|
557
|
+
readonly limit: import("effect/Schema").Int;
|
|
558
|
+
readonly used: import("effect/Schema").Int;
|
|
559
|
+
readonly reserved: import("effect/Schema").Int;
|
|
560
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
561
|
+
}>;
|
|
562
|
+
readonly memoryBytes: import("effect/Schema").Struct<{
|
|
563
|
+
readonly limit: import("effect/Schema").Int;
|
|
564
|
+
readonly used: import("effect/Schema").Int;
|
|
565
|
+
readonly reserved: import("effect/Schema").Int;
|
|
566
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
567
|
+
}>;
|
|
568
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
569
|
+
readonly getResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomainMember", "GET", "/v1/resource-domains/:resourceDomainId/members/:userId", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
570
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
571
|
+
readonly userId: import("effect/Schema").String;
|
|
572
|
+
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
573
|
+
readonly userId: import("effect/Schema").String;
|
|
574
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
575
|
+
readonly version: import("effect/Schema").Int;
|
|
576
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
577
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
578
|
+
readonly grantResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"grantResourceDomainMember", "POST", "/v1/resource-domains/:resourceDomainId/members/:userId/grant", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
579
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
580
|
+
readonly userId: import("effect/Schema").String;
|
|
581
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
582
|
+
readonly version: import("effect/Schema").Int;
|
|
583
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
584
|
+
readonly userId: import("effect/Schema").String;
|
|
585
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
586
|
+
readonly version: import("effect/Schema").Int;
|
|
587
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
588
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
589
|
+
readonly listResourceDomainMembers: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"listResourceDomainMembers", "GET", "/v1/resource-domains/:resourceDomainId/members", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
590
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
591
|
+
}>>, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
592
|
+
readonly limit: import("effect/Schema").optional<import("effect/Schema").FiniteFromString>;
|
|
593
|
+
readonly cursor: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
594
|
+
}>>, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
595
|
+
readonly items: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
596
|
+
readonly userId: import("effect/Schema").String;
|
|
597
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
598
|
+
readonly version: import("effect/Schema").Int;
|
|
599
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
600
|
+
}>>;
|
|
601
|
+
readonly nextCursor: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
602
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
603
|
+
readonly revokeResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"revokeResourceDomainMember", "POST", "/v1/resource-domains/:resourceDomainId/members/:userId/revoke", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
604
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
605
|
+
readonly userId: import("effect/Schema").String;
|
|
606
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
607
|
+
readonly version: import("effect/Schema").Int;
|
|
608
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
609
|
+
readonly userId: import("effect/Schema").String;
|
|
610
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
611
|
+
readonly version: import("effect/Schema").Int;
|
|
612
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
613
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
614
|
+
readonly setResourceDomainBudget: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"setResourceDomainBudget", "PUT", "/v1/resource-domains/:resourceDomainId/budget", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
615
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
616
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
617
|
+
readonly revision: import("effect/Schema").Int;
|
|
618
|
+
readonly cpuMillicores: import("effect/Schema").Int;
|
|
619
|
+
readonly memoryBytes: import("effect/Schema").Int;
|
|
620
|
+
readonly storageBytes: import("effect/Schema").Int;
|
|
621
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
622
|
+
readonly revision: import("effect/Schema").Int;
|
|
623
|
+
readonly storageBytes: import("effect/Schema").Struct<{
|
|
624
|
+
readonly limit: import("effect/Schema").Int;
|
|
625
|
+
readonly used: import("effect/Schema").Int;
|
|
626
|
+
readonly reserved: import("effect/Schema").Int;
|
|
627
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
628
|
+
readonly archived: import("effect/Schema").Int;
|
|
629
|
+
readonly protection: import("effect/Schema").Int;
|
|
630
|
+
}>;
|
|
631
|
+
readonly cpuMillicores: import("effect/Schema").Struct<{
|
|
632
|
+
readonly limit: import("effect/Schema").Int;
|
|
633
|
+
readonly used: import("effect/Schema").Int;
|
|
634
|
+
readonly reserved: import("effect/Schema").Int;
|
|
635
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
636
|
+
}>;
|
|
637
|
+
readonly memoryBytes: import("effect/Schema").Struct<{
|
|
638
|
+
readonly limit: import("effect/Schema").Int;
|
|
639
|
+
readonly used: import("effect/Schema").Int;
|
|
640
|
+
readonly reserved: import("effect/Schema").Int;
|
|
641
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
642
|
+
}>;
|
|
643
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainBudgetRevisionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
543
644
|
};
|
|
544
645
|
readonly runs: {
|
|
545
646
|
readonly createRun: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"createRun", "POST", "/v1/runs/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
@@ -2489,12 +2590,13 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2489
2590
|
readonly resourceDomains: {
|
|
2490
2591
|
readonly ensureResourceDomain: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"ensureResourceDomain", "POST", "/v1/resource-domains/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2491
2592
|
readonly key: import("effect/Schema").String;
|
|
2593
|
+
readonly budget: import("effect/Schema").optional<import("effect/Schema").Struct<Record<"cpuMillicores" | "memoryBytes" | "storageBytes", import("effect/Schema").Int>>>;
|
|
2492
2594
|
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2493
2595
|
readonly resourceDomainId: import("effect/Schema").String;
|
|
2494
2596
|
readonly key: import("effect/Schema").String;
|
|
2495
2597
|
readonly createdAt: import("effect/Schema").String;
|
|
2496
2598
|
readonly created: import("effect/Schema").Boolean;
|
|
2497
|
-
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2599
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainBudgetDiffersError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2498
2600
|
readonly getResourceDomain: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomain", "GET", "/v1/resource-domains/:resourceDomainId", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2499
2601
|
readonly resourceDomainId: import("effect/Schema").String;
|
|
2500
2602
|
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
@@ -2502,6 +2604,106 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2502
2604
|
readonly key: import("effect/Schema").String;
|
|
2503
2605
|
readonly createdAt: import("effect/Schema").String;
|
|
2504
2606
|
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2607
|
+
readonly getResourceDomainBudget: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomainBudget", "GET", "/v1/resource-domains/:resourceDomainId/budget", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2608
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2609
|
+
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2610
|
+
readonly revision: import("effect/Schema").Int;
|
|
2611
|
+
readonly storageBytes: import("effect/Schema").Struct<{
|
|
2612
|
+
readonly limit: import("effect/Schema").Int;
|
|
2613
|
+
readonly used: import("effect/Schema").Int;
|
|
2614
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2615
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2616
|
+
readonly archived: import("effect/Schema").Int;
|
|
2617
|
+
readonly protection: import("effect/Schema").Int;
|
|
2618
|
+
}>;
|
|
2619
|
+
readonly cpuMillicores: import("effect/Schema").Struct<{
|
|
2620
|
+
readonly limit: import("effect/Schema").Int;
|
|
2621
|
+
readonly used: import("effect/Schema").Int;
|
|
2622
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2623
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2624
|
+
}>;
|
|
2625
|
+
readonly memoryBytes: import("effect/Schema").Struct<{
|
|
2626
|
+
readonly limit: import("effect/Schema").Int;
|
|
2627
|
+
readonly used: import("effect/Schema").Int;
|
|
2628
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2629
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2630
|
+
}>;
|
|
2631
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2632
|
+
readonly getResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"getResourceDomainMember", "GET", "/v1/resource-domains/:resourceDomainId/members/:userId", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2633
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2634
|
+
readonly userId: import("effect/Schema").String;
|
|
2635
|
+
}>>, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2636
|
+
readonly userId: import("effect/Schema").String;
|
|
2637
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
2638
|
+
readonly version: import("effect/Schema").Int;
|
|
2639
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
2640
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2641
|
+
readonly grantResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"grantResourceDomainMember", "POST", "/v1/resource-domains/:resourceDomainId/members/:userId/grant", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2642
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2643
|
+
readonly userId: import("effect/Schema").String;
|
|
2644
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2645
|
+
readonly version: import("effect/Schema").Int;
|
|
2646
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2647
|
+
readonly userId: import("effect/Schema").String;
|
|
2648
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
2649
|
+
readonly version: import("effect/Schema").Int;
|
|
2650
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
2651
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2652
|
+
readonly listResourceDomainMembers: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"listResourceDomainMembers", "GET", "/v1/resource-domains/:resourceDomainId/members", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2653
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2654
|
+
}>>, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2655
|
+
readonly limit: import("effect/Schema").optional<import("effect/Schema").FiniteFromString>;
|
|
2656
|
+
readonly cursor: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
2657
|
+
}>>, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2658
|
+
readonly items: import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
2659
|
+
readonly userId: import("effect/Schema").String;
|
|
2660
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
2661
|
+
readonly version: import("effect/Schema").Int;
|
|
2662
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
2663
|
+
}>>;
|
|
2664
|
+
readonly nextCursor: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
2665
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2666
|
+
readonly revokeResourceDomainMember: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"revokeResourceDomainMember", "POST", "/v1/resource-domains/:resourceDomainId/members/:userId/revoke", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2667
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2668
|
+
readonly userId: import("effect/Schema").String;
|
|
2669
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2670
|
+
readonly version: import("effect/Schema").Int;
|
|
2671
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2672
|
+
readonly userId: import("effect/Schema").String;
|
|
2673
|
+
readonly state: import("effect/Schema").Literals<readonly ["member", "revoked"]>;
|
|
2674
|
+
readonly version: import("effect/Schema").Int;
|
|
2675
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
2676
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2677
|
+
readonly setResourceDomainBudget: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"setResourceDomainBudget", "PUT", "/v1/resource-domains/:resourceDomainId/budget", import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
|
|
2678
|
+
readonly resourceDomainId: import("effect/Schema").String;
|
|
2679
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2680
|
+
readonly revision: import("effect/Schema").Int;
|
|
2681
|
+
readonly cpuMillicores: import("effect/Schema").Int;
|
|
2682
|
+
readonly memoryBytes: import("effect/Schema").Int;
|
|
2683
|
+
readonly storageBytes: import("effect/Schema").Int;
|
|
2684
|
+
}>>, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
2685
|
+
readonly revision: import("effect/Schema").Int;
|
|
2686
|
+
readonly storageBytes: import("effect/Schema").Struct<{
|
|
2687
|
+
readonly limit: import("effect/Schema").Int;
|
|
2688
|
+
readonly used: import("effect/Schema").Int;
|
|
2689
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2690
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2691
|
+
readonly archived: import("effect/Schema").Int;
|
|
2692
|
+
readonly protection: import("effect/Schema").Int;
|
|
2693
|
+
}>;
|
|
2694
|
+
readonly cpuMillicores: import("effect/Schema").Struct<{
|
|
2695
|
+
readonly limit: import("effect/Schema").Int;
|
|
2696
|
+
readonly used: import("effect/Schema").Int;
|
|
2697
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2698
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2699
|
+
}>;
|
|
2700
|
+
readonly memoryBytes: import("effect/Schema").Struct<{
|
|
2701
|
+
readonly limit: import("effect/Schema").Int;
|
|
2702
|
+
readonly used: import("effect/Schema").Int;
|
|
2703
|
+
readonly reserved: import("effect/Schema").Int;
|
|
2704
|
+
readonly warning: import("effect/Schema").Literals<readonly ["none", "80-percent", "95-percent", "full"]>;
|
|
2705
|
+
}>;
|
|
2706
|
+
}>>, import("effect/Schema").toCodecJson<typeof import("@sealant/api-contracts").ResourceDomainForbiddenError | typeof import("@sealant/api-contracts").ResourceDomainNotFoundError | typeof import("@sealant/api-contracts").ResourceDomainBudgetRevisionConflictError | typeof import("@sealant/api-contracts").ResourceDomainInternalServerError>, import("@sealant/api-contracts").RequestRefusal, never>, never, never>;
|
|
2505
2707
|
};
|
|
2506
2708
|
readonly runs: {
|
|
2507
2709
|
readonly createRun: HttpApiClient.Client.Method<import("effect/http-api/HttpApiEndpoint").HttpApiEndpoint<"createRun", "POST", "/v1/runs/", never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
|
|
@@ -1434,3 +1434,103 @@ export declare const archiveSshKeyOp: (sshKeyId: string, ownerUserId: string) =>
|
|
|
1434
1434
|
readonly fingerprint: string;
|
|
1435
1435
|
readonly createdAt: string;
|
|
1436
1436
|
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").SshKeyInternalServerError | import("@sealant/api-contracts").SshKeyNotFoundError, SealantApiClient>;
|
|
1437
|
+
export declare const ensureResourceDomainOp: (key: string, budget?: {
|
|
1438
|
+
readonly cpuMillicores: number;
|
|
1439
|
+
readonly memoryBytes: number;
|
|
1440
|
+
readonly storageBytes: number;
|
|
1441
|
+
} | undefined) => Effect.Effect<{
|
|
1442
|
+
readonly resourceDomainId: string;
|
|
1443
|
+
readonly key: string;
|
|
1444
|
+
readonly createdAt: string;
|
|
1445
|
+
readonly created: boolean;
|
|
1446
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainBudgetDiffersError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1447
|
+
export declare const getResourceDomainOp: (resourceDomainId: string) => Effect.Effect<{
|
|
1448
|
+
readonly resourceDomainId: string;
|
|
1449
|
+
readonly key: string;
|
|
1450
|
+
readonly createdAt: string;
|
|
1451
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1452
|
+
export declare const grantResourceDomainMemberOp: (resourceDomainId: string, userId: string, payload: {
|
|
1453
|
+
readonly version: number;
|
|
1454
|
+
}) => Effect.Effect<{
|
|
1455
|
+
readonly userId: string;
|
|
1456
|
+
readonly state: "member" | "revoked";
|
|
1457
|
+
readonly version: number;
|
|
1458
|
+
readonly updatedAt: string;
|
|
1459
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1460
|
+
export declare const revokeResourceDomainMemberOp: (resourceDomainId: string, userId: string, payload: {
|
|
1461
|
+
readonly version: number;
|
|
1462
|
+
}) => Effect.Effect<{
|
|
1463
|
+
readonly userId: string;
|
|
1464
|
+
readonly state: "member" | "revoked";
|
|
1465
|
+
readonly version: number;
|
|
1466
|
+
readonly updatedAt: string;
|
|
1467
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainMemberVersionConflictError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1468
|
+
export declare const getResourceDomainMemberOp: (resourceDomainId: string, userId: string) => Effect.Effect<{
|
|
1469
|
+
readonly userId: string;
|
|
1470
|
+
readonly state: "member" | "revoked";
|
|
1471
|
+
readonly version: number;
|
|
1472
|
+
readonly updatedAt: string;
|
|
1473
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainMemberNotFoundError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("@sealant/api-contracts").ResourceDomainPersonNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1474
|
+
export declare const listResourceDomainMembersOp: (resourceDomainId: string, query: {
|
|
1475
|
+
readonly limit?: number | undefined;
|
|
1476
|
+
readonly cursor?: string | undefined;
|
|
1477
|
+
}) => Effect.Effect<{
|
|
1478
|
+
readonly items: readonly {
|
|
1479
|
+
readonly userId: string;
|
|
1480
|
+
readonly state: "member" | "revoked";
|
|
1481
|
+
readonly version: number;
|
|
1482
|
+
readonly updatedAt: string;
|
|
1483
|
+
}[];
|
|
1484
|
+
readonly nextCursor?: string | undefined;
|
|
1485
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1486
|
+
export declare const getResourceDomainBudgetOp: (resourceDomainId: string) => Effect.Effect<{
|
|
1487
|
+
readonly revision: number;
|
|
1488
|
+
readonly storageBytes: {
|
|
1489
|
+
readonly limit: number;
|
|
1490
|
+
readonly used: number;
|
|
1491
|
+
readonly reserved: number;
|
|
1492
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1493
|
+
readonly archived: number;
|
|
1494
|
+
readonly protection: number;
|
|
1495
|
+
};
|
|
1496
|
+
readonly cpuMillicores: {
|
|
1497
|
+
readonly limit: number;
|
|
1498
|
+
readonly used: number;
|
|
1499
|
+
readonly reserved: number;
|
|
1500
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1501
|
+
};
|
|
1502
|
+
readonly memoryBytes: {
|
|
1503
|
+
readonly limit: number;
|
|
1504
|
+
readonly used: number;
|
|
1505
|
+
readonly reserved: number;
|
|
1506
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1507
|
+
};
|
|
1508
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
1509
|
+
export declare const setResourceDomainBudgetOp: (resourceDomainId: string, payload: {
|
|
1510
|
+
readonly revision: number;
|
|
1511
|
+
readonly cpuMillicores: number;
|
|
1512
|
+
readonly memoryBytes: number;
|
|
1513
|
+
readonly storageBytes: number;
|
|
1514
|
+
}) => Effect.Effect<{
|
|
1515
|
+
readonly revision: number;
|
|
1516
|
+
readonly storageBytes: {
|
|
1517
|
+
readonly limit: number;
|
|
1518
|
+
readonly used: number;
|
|
1519
|
+
readonly reserved: number;
|
|
1520
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1521
|
+
readonly archived: number;
|
|
1522
|
+
readonly protection: number;
|
|
1523
|
+
};
|
|
1524
|
+
readonly cpuMillicores: {
|
|
1525
|
+
readonly limit: number;
|
|
1526
|
+
readonly used: number;
|
|
1527
|
+
readonly reserved: number;
|
|
1528
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1529
|
+
};
|
|
1530
|
+
readonly memoryBytes: {
|
|
1531
|
+
readonly limit: number;
|
|
1532
|
+
readonly used: number;
|
|
1533
|
+
readonly reserved: number;
|
|
1534
|
+
readonly warning: "80-percent" | "95-percent" | "full" | "none";
|
|
1535
|
+
};
|
|
1536
|
+
}, import("effect/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RequestRefusedError | import("@sealant/api-contracts").ResourceDomainBudgetRevisionConflictError | import("@sealant/api-contracts").ResourceDomainForbiddenError | import("@sealant/api-contracts").ResourceDomainInternalServerError | import("@sealant/api-contracts").ResourceDomainNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
@@ -86,3 +86,20 @@ export const getSetupStateOp = () => Effect.flatMap(SealantApiClient, (client) =
|
|
|
86
86
|
export const createSshKeyOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.sshKeys.createSshKey({ payload }));
|
|
87
87
|
export const listSshKeysOp = (ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.sshKeys.listSshKeys({ query: { ownerUserId } }));
|
|
88
88
|
export const archiveSshKeyOp = (sshKeyId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.sshKeys.archiveSshKey({ params: { sshKeyId }, query: { ownerUserId } }));
|
|
89
|
+
// ---- resource domains (the SDK's scopes) ----
|
|
90
|
+
export const ensureResourceDomainOp = (key, budget) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.ensureResourceDomain({
|
|
91
|
+
payload: budget === undefined ? { key } : { key, budget },
|
|
92
|
+
}));
|
|
93
|
+
export const getResourceDomainOp = (resourceDomainId) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.getResourceDomain({ params: { resourceDomainId } }));
|
|
94
|
+
export const grantResourceDomainMemberOp = (resourceDomainId, userId, payload) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.grantResourceDomainMember({
|
|
95
|
+
params: { resourceDomainId, userId },
|
|
96
|
+
payload,
|
|
97
|
+
}));
|
|
98
|
+
export const revokeResourceDomainMemberOp = (resourceDomainId, userId, payload) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.revokeResourceDomainMember({
|
|
99
|
+
params: { resourceDomainId, userId },
|
|
100
|
+
payload,
|
|
101
|
+
}));
|
|
102
|
+
export const getResourceDomainMemberOp = (resourceDomainId, userId) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.getResourceDomainMember({ params: { resourceDomainId, userId } }));
|
|
103
|
+
export const listResourceDomainMembersOp = (resourceDomainId, query) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.listResourceDomainMembers({ params: { resourceDomainId }, query }));
|
|
104
|
+
export const getResourceDomainBudgetOp = (resourceDomainId) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.getResourceDomainBudget({ params: { resourceDomainId } }));
|
|
105
|
+
export const setResourceDomainBudgetOp = (resourceDomainId, payload) => Effect.flatMap(SealantApiClient, (client) => client.resourceDomains.setResourceDomainBudget({ params: { resourceDomainId }, payload }));
|
package/dist/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export { Sealant } from "./client.js";
|
|
|
18
18
|
export { claudeCode, codex, customHarness, opencode, pi } from "./harness.js";
|
|
19
19
|
export { ForwardDialError, type ForwardDialFailure, type ForwardDialReason, ForwardResetError, SealantApiError, SealantError, SealantNotImplementedError, SealantRuntimeError, } from "./errors.js";
|
|
20
20
|
export type * from "./types.js";
|
|
21
|
+
export type { EnsuredScope, ScopeBudget, ScopeBudgetDimension, ScopeBudgetLimits, ScopeBudgets, ScopeClient, ScopeInfo, ScopeMember, ScopeMemberDecision, ScopeMemberPage, ScopeMembers, ScopesNamespace, } from "./scopes.js";
|
|
21
22
|
export { findWorkspaceEnvReservedRule, findWorkspaceSecretEnvReservedRule, formatWorkspaceEnvIssue, parseWorkspaceEnv, parseWorkspaceSecretEnv, WORKSPACE_ENV_MAX_ENTRIES, WORKSPACE_ENV_MAX_NAME_LENGTH, WORKSPACE_ENV_MAX_TOTAL_BYTES, WORKSPACE_ENV_MAX_VALUE_BYTES, WORKSPACE_ENV_NAME_PATTERN, WORKSPACE_ENV_SECRET_MARKERS, } from "@sealant/api-contracts/workspace-environment";
|
|
22
23
|
export type { WorkspaceEnvIssue, WorkspaceEnvParseResult, WorkspaceEnvReservedRule, } from "@sealant/api-contracts/workspace-environment";
|
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sealant.scopes`: owners that are projects, not people (the control plane's resource domains).
|
|
3
|
+
*
|
|
4
|
+
* An application ensures one scope per project, by a global `<application>:<name>` key, and names
|
|
5
|
+
* the people who may reach it. A scope never holds a login or a provider credential and never runs
|
|
6
|
+
* a harness, so the client that acts as one (`actAs`) has no workspace, run, inference or
|
|
7
|
+
* credential methods at all. These calls need a service key and never use `ownerUserId`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ResourceDomainBudgetDimension } from "@sealant/api-contracts";
|
|
10
|
+
import type { SdkRuntime } from "./effect/runtime.js";
|
|
11
|
+
export interface ScopeInfo {
|
|
12
|
+
/** `rdm:<uuid>`. No person field of the API accepts it. */
|
|
13
|
+
readonly id: string;
|
|
14
|
+
/** `<application>:<name>`, unique across every application. */
|
|
15
|
+
readonly key: string;
|
|
16
|
+
readonly createdAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface EnsuredScope extends ScopeInfo {
|
|
19
|
+
/** True when this call created the scope. */
|
|
20
|
+
readonly created: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The application's latest decision about one person in a scope. A revoked member keeps its row,
|
|
24
|
+
* so its version stays readable.
|
|
25
|
+
*/
|
|
26
|
+
export interface ScopeMember {
|
|
27
|
+
readonly userId: string;
|
|
28
|
+
readonly state: "member" | "revoked";
|
|
29
|
+
readonly version: number;
|
|
30
|
+
readonly updatedAt: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `version` is the application's own number for its decision about this person, rising with each
|
|
34
|
+
* decision it makes (its record's revision, say). The scope keeps the highest. The same version
|
|
35
|
+
* with the same state is a repeat and answers the member unchanged. The same version with the
|
|
36
|
+
* other state, or a lower one, rejects (409, `ResourceDomainMemberVersionConflictError`, whose
|
|
37
|
+
* `current` is the decision that stands) and changes nothing. So a delayed grant never undoes a
|
|
38
|
+
* newer revoke, and nothing needs reading first.
|
|
39
|
+
*/
|
|
40
|
+
export interface ScopeMemberDecision {
|
|
41
|
+
readonly version: number;
|
|
42
|
+
}
|
|
43
|
+
/** A page of a scope's members. `nextCursor` is present when more follow. */
|
|
44
|
+
export interface ScopeMemberPage {
|
|
45
|
+
readonly items: readonly ScopeMember[];
|
|
46
|
+
readonly nextCursor?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface ScopeMembers {
|
|
49
|
+
grant(userId: string, decision: ScopeMemberDecision): Promise<ScopeMember>;
|
|
50
|
+
revoke(userId: string, decision: ScopeMemberDecision): Promise<ScopeMember>;
|
|
51
|
+
/**
|
|
52
|
+
* One person's decision. Rejects with 404 `ResourceDomainMemberNotFoundError` when there is none,
|
|
53
|
+
* `ResourceDomainPersonNotFoundError` when the person does not exist.
|
|
54
|
+
*/
|
|
55
|
+
get(userId: string): Promise<ScopeMember>;
|
|
56
|
+
/**
|
|
57
|
+
* A page of the people with a decision in the scope, revoked ones included, by user id: `limit`
|
|
58
|
+
* of them (100 unless named, at most 500), after the previous page's `nextCursor` as `cursor`.
|
|
59
|
+
*/
|
|
60
|
+
list(options?: {
|
|
61
|
+
readonly limit?: number;
|
|
62
|
+
readonly cursor?: string;
|
|
63
|
+
}): Promise<ScopeMemberPage>;
|
|
64
|
+
}
|
|
65
|
+
/** Ceilings on what a scope's objects may hold (CPU millicores, memory and storage bytes). */
|
|
66
|
+
export type ScopeBudgetLimits = {
|
|
67
|
+
readonly [D in ResourceDomainBudgetDimension]: number;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* `used` (confirmed to exist) and `reserved` (admitted, not yet confirmed) both count against
|
|
71
|
+
* `limit`; `warning` is the highest share of it they reach.
|
|
72
|
+
*/
|
|
73
|
+
export interface ScopeBudgetDimension {
|
|
74
|
+
readonly limit: number;
|
|
75
|
+
readonly used: number;
|
|
76
|
+
readonly reserved: number;
|
|
77
|
+
readonly warning: "none" | "80-percent" | "95-percent" | "full";
|
|
78
|
+
}
|
|
79
|
+
/** Storage is one allowance, archived volumes and protection included; nothing is deleted to free it. */
|
|
80
|
+
export type ScopeBudget = {
|
|
81
|
+
/** Name it to change the budget: a change made since refuses yours. */
|
|
82
|
+
readonly revision: number;
|
|
83
|
+
} & {
|
|
84
|
+
readonly [D in ResourceDomainBudgetDimension]: ScopeBudgetDimension;
|
|
85
|
+
} & {
|
|
86
|
+
readonly storageBytes: {
|
|
87
|
+
readonly archived: number;
|
|
88
|
+
readonly protection: number;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export interface ScopeBudgets {
|
|
92
|
+
get(): Promise<ScopeBudget>;
|
|
93
|
+
/**
|
|
94
|
+
* Replace the budget at the `revision` you read. A change since rejects (409,
|
|
95
|
+
* `ResourceDomainBudgetRevisionConflictError`). It answers the budget it wrote, and changes
|
|
96
|
+
* nothing the scope holds.
|
|
97
|
+
*/
|
|
98
|
+
set(change: ScopeBudgetLimits & {
|
|
99
|
+
readonly revision: number;
|
|
100
|
+
}): Promise<ScopeBudget>;
|
|
101
|
+
}
|
|
102
|
+
/** A client acting as one scope. It has no method that could reach a credential or a harness. */
|
|
103
|
+
export interface ScopeClient {
|
|
104
|
+
readonly id: string;
|
|
105
|
+
get(): Promise<ScopeInfo>;
|
|
106
|
+
readonly members: ScopeMembers;
|
|
107
|
+
readonly budget: ScopeBudgets;
|
|
108
|
+
}
|
|
109
|
+
export interface ScopesNamespace {
|
|
110
|
+
/**
|
|
111
|
+
* The scope with this key, created on the first call (with `budget`, or zero); later and
|
|
112
|
+
* concurrent calls answer it. Naming another budget rejects (409,
|
|
113
|
+
* `ResourceDomainBudgetDiffersError`, carrying the scope's id and its budget's revision).
|
|
114
|
+
*/
|
|
115
|
+
ensure(options: {
|
|
116
|
+
readonly key: string;
|
|
117
|
+
readonly budget?: ScopeBudgetLimits;
|
|
118
|
+
}): Promise<EnsuredScope>;
|
|
119
|
+
get(scopeId: string): Promise<ScopeInfo>;
|
|
120
|
+
/** A client for this scope alone, and the only way to its members. Nothing is checked until its first call. */
|
|
121
|
+
actAs(scopeId: string): ScopeClient;
|
|
122
|
+
}
|
|
123
|
+
export declare const makeScopes: (runtime: SdkRuntime) => ScopesNamespace;
|
package/dist/scopes.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sealant.scopes`: owners that are projects, not people (the control plane's resource domains).
|
|
3
|
+
*
|
|
4
|
+
* An application ensures one scope per project, by a global `<application>:<name>` key, and names
|
|
5
|
+
* the people who may reach it. A scope never holds a login or a provider credential and never runs
|
|
6
|
+
* a harness, so the client that acts as one (`actAs`) has no workspace, run, inference or
|
|
7
|
+
* credential methods at all. These calls need a service key and never use `ownerUserId`.
|
|
8
|
+
*/
|
|
9
|
+
import { RESOURCE_DOMAIN_BUDGET_DIMENSIONS, } from "@sealant/api-contracts";
|
|
10
|
+
import * as Rec from "effect/Record";
|
|
11
|
+
import { ensureResourceDomainOp, getResourceDomainBudgetOp, getResourceDomainMemberOp, getResourceDomainOp, grantResourceDomainMemberOp, listResourceDomainMembersOp, revokeResourceDomainMemberOp, setResourceDomainBudgetOp, } from "./effect/operations.js";
|
|
12
|
+
const toScope = (wire) => ({
|
|
13
|
+
id: wire.resourceDomainId,
|
|
14
|
+
key: wire.key,
|
|
15
|
+
createdAt: wire.createdAt,
|
|
16
|
+
});
|
|
17
|
+
export const makeScopes = (runtime) => {
|
|
18
|
+
const get = async (scopeId) => toScope(await runtime.run(getResourceDomainOp(scopeId)));
|
|
19
|
+
return {
|
|
20
|
+
ensure: async ({ key, budget }) => {
|
|
21
|
+
const wire = await runtime.run(ensureResourceDomainOp(key, budget));
|
|
22
|
+
return { ...toScope(wire), created: wire.created };
|
|
23
|
+
},
|
|
24
|
+
get,
|
|
25
|
+
actAs: (scopeId) => ({
|
|
26
|
+
id: scopeId,
|
|
27
|
+
get: () => get(scopeId),
|
|
28
|
+
members: {
|
|
29
|
+
grant: (userId, decision) => runtime.run(grantResourceDomainMemberOp(scopeId, userId, { version: decision.version })),
|
|
30
|
+
revoke: (userId, decision) => runtime.run(revokeResourceDomainMemberOp(scopeId, userId, { version: decision.version })),
|
|
31
|
+
get: (userId) => runtime.run(getResourceDomainMemberOp(scopeId, userId)),
|
|
32
|
+
list: async (options) => {
|
|
33
|
+
const page = await runtime.run(listResourceDomainMembersOp(scopeId, { ...options }));
|
|
34
|
+
return page.nextCursor === undefined
|
|
35
|
+
? { items: page.items }
|
|
36
|
+
: { items: page.items, nextCursor: page.nextCursor };
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
budget: {
|
|
40
|
+
get: () => runtime.run(getResourceDomainBudgetOp(scopeId)),
|
|
41
|
+
set: (change) => runtime.run(setResourceDomainBudgetOp(scopeId, {
|
|
42
|
+
...Rec.map(RESOURCE_DOMAIN_BUDGET_DIMENSIONS, (_, dimension) => change[dimension]),
|
|
43
|
+
revision: change.revision,
|
|
44
|
+
})),
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/sdk-next",
|
|
3
|
-
"version": "0.40.0-next.
|
|
3
|
+
"version": "0.40.0-next.771",
|
|
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.
|
|
29
|
+
"@sealant/api-contracts": "npm:@sealant/api-contracts-next@0.40.0-next.771"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"effect": "^4.0.5"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "697e8d55f312105e4f52964dd5a7fb956c0c6d63",
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
37
37
|
}
|