@treeseed/sdk 0.13.0-rc.81 → 0.13.0-rc.83

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.
@@ -1 +1 @@
1
- {"completedAt":"2026-09-03T01:31:02.124Z"}
1
+ {"completedAt":"2026-09-03T07:04:23.401Z"}
@@ -1,7 +1,7 @@
1
1
  export declare const ARTIFACT_MUTATION_RECEIPT_SCHEMA: "treeseed.artifact-mutation-receipt/v1";
2
2
  export type ArtifactMutationKind = 'treedx-content' | 'source-checkpoint';
3
3
  export type ArtifactMutationPhase = 'provisional' | 'integrated';
4
- import type { AgentWorkExecutionMode, UpstreamMutationPolicy } from './contracts/support/execution-mode.js';
4
+ import type { AgentWorkExecutionMode, UpstreamMutationPolicy } from './contracts/support/authority/execution-mode.js';
5
5
  export interface ArtifactMutationEvidence {
6
6
  ref: string;
7
7
  digest?: string | null;
@@ -1,5 +1,5 @@
1
1
  export type AgentExecutionMode = 'planning' | 'acting';
2
- export type AgentWorkExecutionMode = import('../../support/execution-mode.js').AgentWorkExecutionMode;
2
+ import type { AgentWorkExecutionMode } from '../../support/authority/execution-mode.js';
3
3
  export type ProviderAssignmentStatus = 'pending' | 'leased' | 'running' | 'completed' | 'failed' | 'returned' | 'expired' | 'cancelled';
4
4
  export type ProviderAssignmentLeaseState = 'unleased' | 'leased' | 'released' | 'expired';
5
5
  export type AgentModeRunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
@@ -1,6 +1,6 @@
1
1
  /** Portable durable records shared by workday control-plane and operator consumers. */
2
2
  import type { WorkdayAgentSelection } from '../../../workday.js';
3
- import type { AgentWorkExecutionMode } from '../../support/execution-mode.js';
3
+ import type { AgentWorkExecutionMode } from '../../support/authority/execution-mode.js';
4
4
  export type CapacityWorkdayRunStatus = 'queued' | 'running' | 'completed' | 'cancelled' | 'failed' | 'degraded';
5
5
  export type CapacityWorkdayEventStatus = 'recorded' | 'active' | 'completed' | 'warning' | 'error' | 'failed';
6
6
  export type CapacityWorkdayDemandSource = 'objective' | 'question' | 'proposal' | 'decision-review' | 'knowledge-gap' | 'release-readiness' | 'idle-intent' | 'planning-input' | 'capacity-plan' | 'assignment-completion' | 'assignment-blockage' | 'workday-summary' | 'handoff' | 'research-workflow';
@@ -1,9 +1,9 @@
1
1
  import type { CapacityPageInfo } from '../../../capacity/capacity-core/capacity-pagination.js';
2
2
  import type { ExecutionCapabilityDemand, ExecutionCapabilitySupply } from '../../../types/agents.js';
3
- import type { AgentCapacityEnvelope, AgentExecutionMode, AgentModeRun, DecisionExecutionInput, ProviderAssignment, ProviderAssignmentSynthesisSource, TreeDxProxyHandle, WorkdayCapacityEnvelope } from '../capacity/assignments/assignment-records.js';
4
- import type { AgentKernelPolicy, AgentKernelProfile } from '../projects/agents/project-agent-class.js';
3
+ import type { AgentCapacityEnvelope, AgentExecutionMode, AgentModeRun, AgentModeRunUsageSettlement, DecisionExecutionInput, ProviderAssignment, ProviderAssignmentSynthesisSource, TreeDxProxyHandle, WorkdayCapacityEnvelope } from '../capacity/assignments/assignment-records.js';
4
+ import type { AgentKernelPolicy, AgentKernelProfile, ProjectAgentClass } from '../projects/agents/project-agent-class.js';
5
5
  import type { CapacityLedgerEntry, CapacityReservation, CapacityUsageActual } from '../support/financial-records.js';
6
- import type { WorkdayCapacityEnvelopeRecord } from '../support/planning-records.js';
6
+ import type { DecisionPlanningStatus, WorkdayCapacityEnvelopeRecord } from '../support/planning-records.js';
7
7
  export type AgentKernelModeExecutionStatus = 'completed' | 'waiting' | 'failed' | 'returned';
8
8
  export type AgentKernelModeFallbackCode = 'assignment_missing_project_or_agent' | 'assignment_governance_provenance_missing' | 'assignment_lease_expired' | 'assignment_mode_not_allowed' | 'assignment_missing_capacity_envelope' | 'assignment_missing_decision_input' | 'assignment_handler_failed' | 'assignment_project_not_synced' | 'assignment_agent_not_found' | 'assignment_insufficient_capability' | 'assignment_decision_not_ready' | 'assignment_capacity_plan_not_accepted' | 'assignment_capacity_not_reserved' | 'assignment_capability_handle_invalid' | 'assignment_capability_handle_secret_material' | 'assignment_capability_handle_write_not_ready' | 'assignment_capability_handle_workspace_denied' | 'assignment_repository_ref_scope_invalid' | 'assignment_workflow_operation_denied' | 'assignment_eligibility_capability_mismatch' | 'assignment_retry_policy_exceeded' | 'assignment_treedx_proxy_scope_invalid' | 'assignment_fallback_quota_exceeded' | 'assignment_output_invalid';
9
9
  export interface AgentCapacityPlan {
@@ -189,7 +189,7 @@ export interface DecisionAssignmentGraph {
189
189
  edges: DecisionAssignmentGraphEdge[];
190
190
  compiledAt?: string | null;
191
191
  compiledBy: 'api-control-plane';
192
- executionMode?: import('./execution-mode.js').AgentWorkExecutionMode;
192
+ executionMode?: import('./authority/execution-mode.js').AgentWorkExecutionMode;
193
193
  metadata?: Record<string, unknown>;
194
194
  }
195
195
  export interface DecisionAssignmentGraphRecord extends DecisionAssignmentGraph {
@@ -2,3 +2,4 @@ export * from '../secrets-capability/service-provider-contracts.js';
2
2
  export * from '../secrets-capability/provider-operation-contracts.js';
3
3
  export * from '../secrets-capability/workflow-operation-contracts.js';
4
4
  export * from '../secrets-capability/service-vault-contracts.js';
5
+ export * from '../secrets-capability/service-vault-crypto.js';
@@ -2,3 +2,4 @@ export * from "../secrets-capability/service-provider-contracts.js";
2
2
  export * from "../secrets-capability/provider-operation-contracts.js";
3
3
  export * from "../secrets-capability/workflow-operation-contracts.js";
4
4
  export * from "../secrets-capability/service-vault-contracts.js";
5
+ export * from "../secrets-capability/service-vault-crypto.js";
@@ -0,0 +1,17 @@
1
+ export declare const SERVICE_VAULT_OPERATIONS: {
2
+ readonly userVaultKey: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
3
+ readonly putUserVaultKey: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
4
+ readonly teamVault: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
5
+ readonly initializeTeamVault: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
6
+ readonly resetTeamVault: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
7
+ readonly rotateTeamVault: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
8
+ readonly vaultGrantCandidates: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
9
+ readonly createVaultGrant: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
10
+ readonly deleteVaultGrant: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
11
+ readonly vaultCredentialEnvelopes: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
12
+ readonly credentialEnvelopes: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
13
+ readonly putCredentialEnvelope: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
14
+ readonly createOperationLease: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
15
+ readonly operationLease: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
16
+ readonly putOperationLeasePayload: import("../../control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
17
+ };
@@ -0,0 +1,114 @@
1
+ import { z } from "zod";
2
+ import { defineOperation } from "../../operation-builder.js";
3
+ const empty = z.object({}).strict();
4
+ const none = z.undefined();
5
+ const record = z.record(z.unknown());
6
+ const teamPath = z.object({ teamId: z.string().min(1) }).strict();
7
+ function vaultOperation(operationId, method, path, pathSchema, options = {}) {
8
+ const read = method === "GET", risk = options.risk ?? "ordinary";
9
+ return defineOperation({
10
+ operationId,
11
+ description: `${read ? "Read" : "Apply"} ${operationId}.`,
12
+ rest: { method, path },
13
+ capability: read ? "secrets.read" : "secrets.write",
14
+ ...path.includes("{") ? { parameters: `treeseed.${operationId}.parameters/v1` } : {},
15
+ authentication: "oauth",
16
+ oauthScopes: read ? ["treeseed:read"] : ["treeseed:projects:write"],
17
+ kind: read ? "read" : "mutation",
18
+ riskClass: risk,
19
+ confirmation: risk === "ordinary" ? "never" : "input_required",
20
+ surfaces: ["rest"],
21
+ cacheScope: read ? "principal" : "none",
22
+ pagination: "none",
23
+ redactedPaths: options.redactedPaths
24
+ }, { path: pathSchema, query: read ? record : empty, body: read ? none : record, output: record });
25
+ }
26
+ const SERVICE_VAULT_OPERATIONS = {
27
+ userVaultKey: vaultOperation("services.vault.user.key.show", "GET", "/v1/users/me/vault-key", empty),
28
+ putUserVaultKey: vaultOperation(
29
+ "services.vault.user.key.put",
30
+ "PUT",
31
+ "/v1/users/me/vault-key",
32
+ empty,
33
+ { risk: "credential", redactedPaths: ["body.encryptedPrivateKeyEnvelope"] }
34
+ ),
35
+ teamVault: vaultOperation("services.vault.team.show", "GET", "/v1/teams/{teamId}/vault", teamPath),
36
+ initializeTeamVault: vaultOperation(
37
+ "services.vault.team.initialize",
38
+ "POST",
39
+ "/v1/teams/{teamId}/vault",
40
+ teamPath,
41
+ { risk: "credential", redactedPaths: ["body.wrappedTeamVaultKey"] }
42
+ ),
43
+ resetTeamVault: vaultOperation(
44
+ "services.vault.team.reset",
45
+ "POST",
46
+ "/v1/teams/{teamId}/vault/reset",
47
+ teamPath,
48
+ { risk: "destructive", redactedPaths: ["body.wrappedTeamVaultKey", "body.currentPassword"] }
49
+ ),
50
+ rotateTeamVault: vaultOperation(
51
+ "services.vault.team.rotate",
52
+ "POST",
53
+ "/v1/teams/{teamId}/vault/rotate",
54
+ teamPath,
55
+ { risk: "credential", redactedPaths: ["body.envelopes", "body.grants"] }
56
+ ),
57
+ vaultGrantCandidates: vaultOperation("services.vault.grant.candidates.list", "GET", "/v1/teams/{teamId}/vault/grant-candidates", teamPath),
58
+ createVaultGrant: vaultOperation(
59
+ "services.vault.grants.create",
60
+ "POST",
61
+ "/v1/teams/{teamId}/vault/grants",
62
+ teamPath,
63
+ { risk: "credential", redactedPaths: ["body.wrappedTeamVaultKey"] }
64
+ ),
65
+ deleteVaultGrant: vaultOperation(
66
+ "services.vault.grants.delete",
67
+ "DELETE",
68
+ "/v1/teams/{teamId}/vault/grants/{grantId}",
69
+ z.object({ teamId: z.string().min(1), grantId: z.string().min(1) }).strict(),
70
+ { risk: "destructive" }
71
+ ),
72
+ vaultCredentialEnvelopes: vaultOperation(
73
+ "services.vault.credential.envelopes.list",
74
+ "GET",
75
+ "/v1/teams/{teamId}/vault/credential-envelopes",
76
+ teamPath
77
+ ),
78
+ credentialEnvelopes: vaultOperation(
79
+ "services.credential.envelopes.list",
80
+ "GET",
81
+ "/v1/teams/{teamId}/services/{connectionId}/credential-envelopes",
82
+ z.object({ teamId: z.string().min(1), connectionId: z.string().min(1) }).strict()
83
+ ),
84
+ putCredentialEnvelope: vaultOperation(
85
+ "services.credential.envelopes.put",
86
+ "POST",
87
+ "/v1/teams/{teamId}/services/{connectionId}/credential-envelopes",
88
+ z.object({ teamId: z.string().min(1), connectionId: z.string().min(1) }).strict(),
89
+ { risk: "credential", redactedPaths: ["body.envelope"] }
90
+ ),
91
+ createOperationLease: vaultOperation(
92
+ "services.operation.leases.create",
93
+ "POST",
94
+ "/v1/teams/{teamId}/service-operation-leases",
95
+ teamPath,
96
+ { risk: "authority" }
97
+ ),
98
+ operationLease: vaultOperation(
99
+ "services.operation.leases.show",
100
+ "GET",
101
+ "/v1/teams/{teamId}/service-operation-leases/{leaseId}",
102
+ z.object({ teamId: z.string().min(1), leaseId: z.string().min(1) }).strict()
103
+ ),
104
+ putOperationLeasePayload: vaultOperation(
105
+ "services.operation.leases.payload.put",
106
+ "PUT",
107
+ "/v1/teams/{teamId}/service-operation-leases/{leaseId}/payload",
108
+ z.object({ teamId: z.string().min(1), leaseId: z.string().min(1) }).strict(),
109
+ { risk: "credential", redactedPaths: ["body.sealedPayload"] }
110
+ )
111
+ };
112
+ export {
113
+ SERVICE_VAULT_OPERATIONS
114
+ };
@@ -1323,6 +1323,21 @@ export declare const CONTROL_PLANE_OPERATIONS: {
1323
1323
  profileId: string;
1324
1324
  connectionId: string;
1325
1325
  }, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1326
+ readonly userVaultKey: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1327
+ readonly putUserVaultKey: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1328
+ readonly teamVault: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1329
+ readonly initializeTeamVault: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1330
+ readonly resetTeamVault: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1331
+ readonly rotateTeamVault: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1332
+ readonly vaultGrantCandidates: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1333
+ readonly createVaultGrant: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1334
+ readonly deleteVaultGrant: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1335
+ readonly vaultCredentialEnvelopes: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1336
+ readonly credentialEnvelopes: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1337
+ readonly putCredentialEnvelope: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1338
+ readonly createOperationLease: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1339
+ readonly operationLease: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1340
+ readonly putOperationLeasePayload: import("./control-plane-operation.js").ControlPlaneOperationBinding<any, {}, Record<string, unknown> | undefined, Record<string, unknown>>;
1326
1341
  };
1327
1342
  readonly agents: {
1328
1343
  readonly list: import("./control-plane-operation.js").ControlPlaneOperationBinding<{
@@ -8,6 +8,7 @@ import { capabilityOntologyOperations } from "./catalog/capability-ontology-oper
8
8
  import { knowledgeShareOperations } from "./catalog/knowledge-share-operations.js";
9
9
  import { PROVIDER_ENVIRONMENT_OPERATIONS } from "./catalog/provider-environment-operations.js";
10
10
  import { HOSTED_TOPOLOGY_OPERATIONS } from "./catalog/hosted-topology-operations.js";
11
+ import { SERVICE_VAULT_OPERATIONS } from "./catalog/services/service-vault-operations.js";
11
12
  import { buildControlPlaneCatalog, flattenControlPlaneOperations } from "./catalog/control-plane-catalog.js";
12
13
  const empty = z.object({}).strict(), none = z.undefined(), record = z.record(z.unknown()), payload = record;
13
14
  function read(operationId, path, capability, surfaces = ["rest"]) {
@@ -277,6 +278,7 @@ const CONTROL_PLANE_OPERATIONS = {
277
278
  deleteWorkflowVariable: resource("repositories.workflow.variables.delete", "DELETE", "/v1/projects/{projectId}/workflow-configuration/variables/{name}", { projectId: z.string().min(1), name: z.string().min(1) }, { capability: "workflows.write", risk: "destructive", concurrency: true })
278
279
  },
279
280
  services: {
281
+ ...SERVICE_VAULT_OPERATIONS,
280
282
  providers: resource("services.providers.list", "GET", "/v1/service-providers", {}, { capability: "services.read", surfaces: ["rest", "cli", "mcp_tool"] }),
281
283
  connections: resource("services.connections.list", "GET", "/v1/teams/{teamId}/services", { teamId: z.string().min(1) }, { capability: "services.read", surfaces: ["rest", "cli", "mcp_tool"], pagination: "cursor" }),
282
284
  connection: resource("services.connections.show", "GET", "/v1/teams/{teamId}/services/{connectionId}", { teamId: z.string().min(1), connectionId: z.string().min(1) }, { capability: "services.read", surfaces: ["rest", "cli", "mcp_resource"] }),
@@ -335,12 +337,12 @@ const CONTROL_PLANE_OPERATIONS = {
335
337
  retry: resource("assignments.retry", "POST", "/v1/teams/{teamId}/capacity/assignments/{assignmentId}/requeue", { teamId: z.string().min(1), assignmentId: z.string().min(1) }, { capability: "assignments.execute", scopes: ["treeseed:execution"], surfaces: ["rest", "cli", "mcp_tool"], risk: "authority" })
336
338
  },
337
339
  operations: {
338
- list: resource("operations.list", "GET", "/v1/platform/operations", {}, { capability: "operations.read", surfaces: ["rest", "mcp_tool"], pagination: "cursor" }),
340
+ list: resource("operations.list", "GET", "/v1/platform/operations", {}, { capability: "operations.read", surfaces: ["rest", "cli", "mcp_tool"], pagination: "cursor" }),
339
341
  create: resource("operations.create", "POST", "/v1/platform/operations", {}, { capability: "operations.execute", scopes: ["treeseed:execution"] }),
340
- show: resource("operations.show", "GET", "/v1/platform/operations/{operationId}", { operationId: z.string().min(1) }, { capability: "operations.read", surfaces: ["rest", "mcp_resource"] }),
342
+ show: resource("operations.show", "GET", "/v1/platform/operations/{operationId}", { operationId: z.string().min(1) }, { capability: "operations.read", surfaces: ["rest", "cli", "mcp_resource"] }),
341
343
  events: resource("operations.events.list", "GET", "/v1/platform/operations/{operationId}/events", { operationId: z.string().min(1) }, { capability: "operations.read", pagination: "cursor" }),
342
344
  cancel: resource("operations.cancel", "POST", "/v1/platform/operations/{operationId}/cancel", { operationId: z.string().min(1) }, { capability: "operations.execute", scopes: ["treeseed:execution"], risk: "destructive" }),
343
- retry: resource("operations.retry", "POST", "/v1/platform/operations/{operationId}/retry", { operationId: z.string().min(1) }, { capability: "operations.execute", scopes: ["treeseed:execution"] })
345
+ retry: resource("operations.retry", "POST", "/v1/platform/operations/{operationId}/retry", { operationId: z.string().min(1) }, { capability: "operations.execute", scopes: ["treeseed:execution"], surfaces: ["rest", "cli"] })
344
346
  },
345
347
  seeds: {
346
348
  runs: resource("seeds.runs.list", "GET", "/v1/seeds/runs", {}, { capability: "seeds.read", pagination: "cursor" }),
@@ -61,10 +61,10 @@ const SERVICE_PROVIDER_CATALOG = [
61
61
  {
62
62
  id: "github-repository-app",
63
63
  label: "Repository Connector App",
64
- description: "Installation authority narrowed to one repository for guarded Git reads and writes.",
64
+ description: "Installation authority for governed repository creation and guarded Git reads and writes.",
65
65
  capabilities: ["repository-hosting"],
66
66
  fields: [],
67
- permissions: ["Metadata: read", "Contents: read and write"],
67
+ permissions: ["Metadata: read", "Contents: read and write", "Checks: read", "Administration: read and write"],
68
68
  sharing: "capability-scoped",
69
69
  unattendedCompatible: true,
70
70
  authoritySchemes: ["app-installation"],
@@ -130,9 +130,9 @@ const SERVICE_PROVIDER_CATALOG = [
130
130
  { type: "object-storage", label: "Object storage", description: "R2-backed immutable publication and private artifact storage.", credentialProfileIds: ["cloudflare-storage"], status: "available" }
131
131
  ],
132
132
  credentialProfiles: [
133
- { id: "cloudflare-runtime", label: "Pages and Workers token", description: "A token limited to application deployment resources.", capabilities: ["frontend-hosting"], fields: [field("apiToken", "API token", "Encrypted in this browser and used only for authorized frontend operations.", true, true)], permissions: ["Account: Workers Scripts Edit", "Account: Pages Edit"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] },
134
- { id: "cloudflare-dns", label: "DNS token", description: "A token restricted to selected zones.", capabilities: ["dns-management"], fields: [field("apiToken", "DNS API token", "Encrypted separately from deployment authority.", true, true)], permissions: ["Zone: DNS Edit for only the managed zones"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] },
135
- { id: "cloudflare-storage", label: "Storage authority", description: "Vault-custodied R2 management and S3-compatible state credentials, isolated from runtime and DNS authority.", capabilities: ["object-storage"], fields: [field("apiToken", "Storage API token", "Encrypted separately and used only to reconcile authorized R2 resources.", true, true), field("accessKeyId", "R2 access key ID", "Vault-custodied S3-compatible access key identifier for encrypted OpenTofu state.", true, true), field("secretAccessKey", "R2 secret access key", "Vault-custodied S3-compatible secret key for encrypted OpenTofu state.", true, true)], permissions: ["Account: Workers R2 Storage Edit", "Object read and write for only the managed state bucket"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] }
133
+ { id: "cloudflare-runtime", label: "Pages and Workers token", description: "A token limited to application deployment resources.", capabilities: ["frontend-hosting"], fields: [field("apiToken", "API token", "Encrypted in this browser and used only for authorized frontend operations.", true, true)], permissions: ["Account: Workers Scripts Edit", "Account: Pages Edit"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "client-encrypted", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] },
134
+ { id: "cloudflare-dns", label: "DNS token", description: "A token restricted to selected zones.", capabilities: ["dns-management"], fields: [field("apiToken", "DNS API token", "Encrypted separately from deployment authority.", true, true)], permissions: ["Zone: DNS Edit for only the managed zones"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "client-encrypted", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] },
135
+ { id: "cloudflare-storage", label: "Storage authority", description: "Vault-custodied R2 management and S3-compatible state credentials, isolated from runtime and DNS authority.", capabilities: ["object-storage"], fields: [field("apiToken", "Storage API token", "Encrypted separately and used only to reconcile authorized R2 resources.", true, true), field("accessKeyId", "R2 access key ID", "Vault-custodied S3-compatible access key identifier for encrypted OpenTofu state.", true, true), field("secretAccessKey", "R2 secret access key", "Vault-custodied S3-compatible secret key for encrypted OpenTofu state.", true, true), field("stateEncryptionKey", "OpenTofu state encryption key", "Generated in the browser and encrypted separately; never store this key with the R2 state object.", true, true)], permissions: ["Account: Workers R2 Storage Edit", "Object read and write for only the managed state bucket"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "client-encrypted", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] }
136
136
  ]
137
137
  },
138
138
  {
@@ -163,7 +163,7 @@ const SERVICE_PROVIDER_CATALOG = [
163
163
  permissions: ["Workspace access required by the selected operations"],
164
164
  sharing: "provider-shared",
165
165
  unattendedCompatible: true,
166
- authoritySchemes: ["environment-reference", "external-vault", "workload-identity"],
166
+ authoritySchemes: ["environment-reference", "client-encrypted", "external-vault", "workload-identity"],
167
167
  knowledgePageIds: ["provider.railway", "services.credentials", "vault.rotation"]
168
168
  }]
169
169
  },
@@ -2,6 +2,9 @@ export declare const SERVICE_VAULT_ENCRYPTION_VERSION: "service-vault-v1";
2
2
  export declare const SERVICE_VAULT_AEAD_ALGORITHM: "xchacha20-poly1305-ietf";
3
3
  export declare const SERVICE_VAULT_KEY_AGREEMENT: "x25519-sealed-box";
4
4
  export declare const SERVICE_VAULT_KDF: "argon2id";
5
+ export declare const SECRET_OPERATION_PURPOSES: readonly ["provider-connection-validation", "remote-git-publication", "workflow-dispatch", "workflow-configuration", "hosted-topology-plan", "hosted-topology-apply", "hosted-topology-readback", "hosted-topology-rollback"];
6
+ export type SecretOperationPurpose = (typeof SECRET_OPERATION_PURPOSES)[number];
7
+ export type HostedSecretOperationPurpose = Extract<SecretOperationPurpose, `hosted-topology-${string}`>;
5
8
  export type EncryptedCredentialEnvelope = {
6
9
  version: typeof SERVICE_VAULT_ENCRYPTION_VERSION;
7
10
  algorithm: typeof SERVICE_VAULT_AEAD_ALGORITHM;
@@ -37,7 +40,7 @@ export type SecretOperationLease = {
37
40
  teamId: string;
38
41
  connectionId: string;
39
42
  capabilityType: string;
40
- purpose: 'provider-connection-validation' | 'remote-git-publication' | 'workflow-dispatch' | 'workflow-configuration';
43
+ purpose: SecretOperationPurpose;
41
44
  resourceScope: Record<string, string>;
42
45
  credentialProfileId: string;
43
46
  actorUserId: string;
@@ -47,6 +50,47 @@ export type SecretOperationLease = {
47
50
  expiresAt: string;
48
51
  consumedAt?: string | null;
49
52
  operationCorrelationId: string;
53
+ hostedBinding?: HostedSecretOperationBinding;
54
+ authorityRequests?: SecretOperationAuthorityRequest[];
55
+ };
56
+ export type HostedSecretOperationBinding = {
57
+ subjectType: 'declaration' | 'plan' | 'rollback';
58
+ subjectDigest: string;
59
+ deploymentId: string;
60
+ stackId: string;
61
+ environment: 'staging' | 'production';
62
+ };
63
+ export type SecretOperationAuthorityRequest = {
64
+ requestId: string;
65
+ connectionId: string;
66
+ credentialProfileId: string;
67
+ provider: 'cloudflare' | 'railway' | 'treeseed';
68
+ purpose: 'provider' | 'state-backend' | 'state-encryption';
69
+ capabilities: string[];
70
+ requiredFields: string[];
71
+ secretRef?: string;
72
+ };
73
+ export type SealedSecretOperationPayload = {
74
+ schemaVersion: 'treeseed.sealed-secret-operation-payload/v1';
75
+ leaseId: string;
76
+ teamId: string;
77
+ operationCorrelationId: string;
78
+ hostedBinding: HostedSecretOperationBinding;
79
+ algorithm: typeof SERVICE_VAULT_KEY_AGREEMENT;
80
+ ciphertext: string;
81
+ };
82
+ export type SecretOperationCredentialBundle = {
83
+ schemaVersion: 'treeseed.secret-operation-credential-bundle/v1';
84
+ leaseId: string;
85
+ teamId: string;
86
+ operationCorrelationId: string;
87
+ hostedBinding: HostedSecretOperationBinding;
88
+ materials: Array<{
89
+ requestId: string;
90
+ connectionId: string;
91
+ credentialProfileId: string;
92
+ values: Record<string, string>;
93
+ }>;
50
94
  };
51
95
  export type ServiceVaultAssociatedData = {
52
96
  teamId: string;
@@ -58,4 +102,7 @@ export type ServiceVaultAssociatedData = {
58
102
  };
59
103
  export declare function containsForbiddenPlaintextSecretMaterial(value: unknown, path?: string): string[];
60
104
  export declare function canonicalServiceVaultAssociatedData(input: ServiceVaultAssociatedData): string;
105
+ export declare function canonicalHostedSecretOperationBinding(input: HostedSecretOperationBinding): string;
106
+ export declare function validateHostedSecretOperationBinding(value: unknown): value is HostedSecretOperationBinding;
107
+ export declare function validateSealedSecretOperationPayload(value: unknown): value is SealedSecretOperationPayload;
61
108
  export declare function validateEncryptedCredentialEnvelope(value: unknown): value is EncryptedCredentialEnvelope;
@@ -2,6 +2,16 @@ const SERVICE_VAULT_ENCRYPTION_VERSION = "service-vault-v1";
2
2
  const SERVICE_VAULT_AEAD_ALGORITHM = "xchacha20-poly1305-ietf";
3
3
  const SERVICE_VAULT_KEY_AGREEMENT = "x25519-sealed-box";
4
4
  const SERVICE_VAULT_KDF = "argon2id";
5
+ const SECRET_OPERATION_PURPOSES = [
6
+ "provider-connection-validation",
7
+ "remote-git-publication",
8
+ "workflow-dispatch",
9
+ "workflow-configuration",
10
+ "hosted-topology-plan",
11
+ "hosted-topology-apply",
12
+ "hosted-topology-readback",
13
+ "hosted-topology-rollback"
14
+ ];
5
15
  const FORBIDDEN_SECRET_KEYS = /(?:passphrase|password|plaintext|derivedKey|privateKey|apiToken|accessToken|secretValue|credentialValue)$/iu;
6
16
  function containsForbiddenPlaintextSecretMaterial(value, path = "") {
7
17
  if (!value || typeof value !== "object") return [];
@@ -23,17 +33,42 @@ function canonicalServiceVaultAssociatedData(input) {
23
33
  version: input.version
24
34
  });
25
35
  }
36
+ const digest = /^sha256:[a-f0-9]{64}$/u;
37
+ const identifier = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
38
+ function canonicalHostedSecretOperationBinding(input) {
39
+ return JSON.stringify({
40
+ subjectType: input.subjectType,
41
+ subjectDigest: input.subjectDigest,
42
+ deploymentId: input.deploymentId,
43
+ stackId: input.stackId,
44
+ environment: input.environment
45
+ });
46
+ }
47
+ function validateHostedSecretOperationBinding(value) {
48
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
49
+ const binding = value;
50
+ return ["declaration", "plan", "rollback"].includes(String(binding.subjectType)) && digest.test(String(binding.subjectDigest)) && identifier.test(String(binding.deploymentId)) && identifier.test(String(binding.stackId)) && ["staging", "production"].includes(String(binding.environment));
51
+ }
52
+ function validateSealedSecretOperationPayload(value) {
53
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
54
+ const payload = value;
55
+ return payload.schemaVersion === "treeseed.sealed-secret-operation-payload/v1" && payload.algorithm === SERVICE_VAULT_KEY_AGREEMENT && [payload.leaseId, payload.teamId, payload.operationCorrelationId, payload.ciphertext].every((field) => typeof field === "string" && field.length > 0) && validateHostedSecretOperationBinding(payload.hostedBinding);
56
+ }
26
57
  function validateEncryptedCredentialEnvelope(value) {
27
58
  if (!value || typeof value !== "object") return false;
28
59
  const envelope = value;
29
60
  return envelope.version === SERVICE_VAULT_ENCRYPTION_VERSION && envelope.algorithm === SERVICE_VAULT_AEAD_ALGORITHM && [envelope.ciphertext, envelope.nonce, envelope.wrappedKey, envelope.wrappedKeyNonce, envelope.associatedData, envelope.associatedDataDigest, envelope.fingerprint].every((field) => typeof field === "string" && field.length > 0);
30
61
  }
31
62
  export {
63
+ SECRET_OPERATION_PURPOSES,
32
64
  SERVICE_VAULT_AEAD_ALGORITHM,
33
65
  SERVICE_VAULT_ENCRYPTION_VERSION,
34
66
  SERVICE_VAULT_KDF,
35
67
  SERVICE_VAULT_KEY_AGREEMENT,
68
+ canonicalHostedSecretOperationBinding,
36
69
  canonicalServiceVaultAssociatedData,
37
70
  containsForbiddenPlaintextSecretMaterial,
38
- validateEncryptedCredentialEnvelope
71
+ validateEncryptedCredentialEnvelope,
72
+ validateHostedSecretOperationBinding,
73
+ validateSealedSecretOperationPayload
39
74
  };
@@ -0,0 +1,20 @@
1
+ import { type EncryptedCredentialEnvelope, type EncryptedPrivateKeyEnvelope, type TeamVaultGrantEnvelope } from '@treeseed/sdk/secrets-capability';
2
+ export declare function createServiceVaultKey(): Promise<Uint8Array>;
3
+ export declare function createServiceVaultUserKeyPair(): Promise<{
4
+ publicKey: string;
5
+ privateKey: Uint8Array;
6
+ }>;
7
+ export declare function encryptServiceVaultPrivateKey(privateKey: Uint8Array, publicKey: string, passphrase: string, options?: {
8
+ opsLimit?: number;
9
+ memLimit?: number;
10
+ }): Promise<EncryptedPrivateKeyEnvelope>;
11
+ export declare function decryptServiceVaultPrivateKey(envelope: EncryptedPrivateKeyEnvelope, passphrase: string): Promise<Uint8Array>;
12
+ export declare function createTeamVaultGrant(teamVaultKey: Uint8Array, recipientPublicKey: string): Promise<TeamVaultGrantEnvelope>;
13
+ export declare function openTeamVaultGrant(grant: TeamVaultGrantEnvelope, recipientPrivateKey: Uint8Array): Promise<Uint8Array>;
14
+ export declare function encryptServiceCredential(plaintext: string, teamVaultKey: Uint8Array, associatedData: string): Promise<EncryptedCredentialEnvelope>;
15
+ export declare function decryptServiceCredential(envelope: EncryptedCredentialEnvelope, teamVaultKey: Uint8Array, expectedAssociatedData: string): Promise<string>;
16
+ export declare function rewrapServiceCredential(envelope: EncryptedCredentialEnvelope, currentTeamVaultKey: Uint8Array, replacementTeamVaultKey: Uint8Array): Promise<EncryptedCredentialEnvelope>;
17
+ export declare function sealSecretOperationPayload(values: Record<string, string>, operationPublicKey: string): Promise<string>;
18
+ export declare function encryptGitHubActionsSecret(value: string, providerPublicKey: string): Promise<string>;
19
+ export declare function openSecretOperationPayload(sealedPayload: string, operationPublicKey: string, operationPrivateKey: Uint8Array): Promise<Record<string, string>>;
20
+ export declare function clearServiceVaultKey(value: Uint8Array | undefined): void;
@@ -0,0 +1,210 @@
1
+ import sodium from "libsodium-wrappers-sumo";
2
+ import {
3
+ SERVICE_VAULT_AEAD_ALGORITHM,
4
+ SERVICE_VAULT_ENCRYPTION_VERSION,
5
+ SERVICE_VAULT_KDF,
6
+ SERVICE_VAULT_KEY_AGREEMENT
7
+ } from "@treeseed/sdk/secrets-capability";
8
+ const b64 = () => sodium.base64_variants.ORIGINAL;
9
+ const encode = (value) => sodium.to_base64(value, b64());
10
+ const decode = (value) => sodium.from_base64(value, b64());
11
+ const hash = (value, key = null) => encode(sodium.crypto_generichash(32, value, key));
12
+ async function ready() {
13
+ await sodium.ready;
14
+ return sodium;
15
+ }
16
+ function validKey(value, length, label) {
17
+ if (!(value instanceof Uint8Array) || value.length !== length) throw new Error(`${label} is invalid.`);
18
+ return value;
19
+ }
20
+ async function createServiceVaultKey() {
21
+ const crypto = await ready();
22
+ return crypto.randombytes_buf(crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
23
+ }
24
+ async function createServiceVaultUserKeyPair() {
25
+ const crypto = await ready(), pair = crypto.crypto_box_keypair();
26
+ return { publicKey: encode(pair.publicKey), privateKey: pair.privateKey };
27
+ }
28
+ async function encryptServiceVaultPrivateKey(privateKey, publicKey, passphrase, options = {}) {
29
+ const crypto = await ready();
30
+ validKey(privateKey, crypto.crypto_box_SECRETKEYBYTES, "Service-vault private key");
31
+ validKey(decode(publicKey), crypto.crypto_box_PUBLICKEYBYTES, "Service-vault public key");
32
+ if (passphrase.length < 12) throw new Error("Service-vault passphrase must contain at least 12 characters.");
33
+ const salt = crypto.randombytes_buf(crypto.crypto_pwhash_SALTBYTES);
34
+ const opsLimit = options.opsLimit ?? crypto.crypto_pwhash_OPSLIMIT_MODERATE;
35
+ const memLimit = options.memLimit ?? crypto.crypto_pwhash_MEMLIMIT_MODERATE;
36
+ const key = crypto.crypto_pwhash(
37
+ crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
38
+ passphrase,
39
+ salt,
40
+ opsLimit,
41
+ memLimit,
42
+ crypto.crypto_pwhash_ALG_ARGON2ID13
43
+ );
44
+ const nonce = crypto.randombytes_buf(crypto.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
45
+ try {
46
+ return {
47
+ version: SERVICE_VAULT_ENCRYPTION_VERSION,
48
+ algorithm: SERVICE_VAULT_AEAD_ALGORITHM,
49
+ kdf: { algorithm: SERVICE_VAULT_KDF, opsLimit, memLimit, salt: encode(salt) },
50
+ nonce: encode(nonce),
51
+ ciphertext: encode(crypto.crypto_aead_xchacha20poly1305_ietf_encrypt(privateKey, publicKey, null, nonce, key)),
52
+ publicKey
53
+ };
54
+ } finally {
55
+ crypto.memzero(key);
56
+ }
57
+ }
58
+ async function decryptServiceVaultPrivateKey(envelope, passphrase) {
59
+ const crypto = await ready();
60
+ if (envelope.version !== SERVICE_VAULT_ENCRYPTION_VERSION || envelope.algorithm !== SERVICE_VAULT_AEAD_ALGORITHM || envelope.kdf.algorithm !== SERVICE_VAULT_KDF) throw new Error("Service-vault private-key envelope is unsupported.");
61
+ if (!Number.isSafeInteger(envelope.kdf.opsLimit) || !Number.isSafeInteger(envelope.kdf.memLimit) || envelope.kdf.opsLimit < crypto.crypto_pwhash_OPSLIMIT_INTERACTIVE || envelope.kdf.opsLimit > crypto.crypto_pwhash_OPSLIMIT_SENSITIVE || envelope.kdf.memLimit < crypto.crypto_pwhash_MEMLIMIT_INTERACTIVE || envelope.kdf.memLimit > crypto.crypto_pwhash_MEMLIMIT_SENSITIVE)
62
+ throw new Error("Service-vault private-key KDF parameters are invalid.");
63
+ const key = crypto.crypto_pwhash(
64
+ crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
65
+ passphrase,
66
+ decode(envelope.kdf.salt),
67
+ envelope.kdf.opsLimit,
68
+ envelope.kdf.memLimit,
69
+ crypto.crypto_pwhash_ALG_ARGON2ID13
70
+ );
71
+ try {
72
+ return validKey(crypto.crypto_aead_xchacha20poly1305_ietf_decrypt(
73
+ null,
74
+ decode(envelope.ciphertext),
75
+ envelope.publicKey,
76
+ decode(envelope.nonce),
77
+ key
78
+ ), crypto.crypto_box_SECRETKEYBYTES, "Decrypted service-vault private key");
79
+ } catch {
80
+ throw new Error("Service-vault passphrase or private-key envelope is invalid.");
81
+ } finally {
82
+ crypto.memzero(key);
83
+ }
84
+ }
85
+ async function createTeamVaultGrant(teamVaultKey, recipientPublicKey) {
86
+ const crypto = await ready();
87
+ validKey(teamVaultKey, crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "Team vault key");
88
+ const publicKey = validKey(decode(recipientPublicKey), crypto.crypto_box_PUBLICKEYBYTES, "Recipient public key");
89
+ return {
90
+ version: SERVICE_VAULT_ENCRYPTION_VERSION,
91
+ algorithm: SERVICE_VAULT_KEY_AGREEMENT,
92
+ recipientPublicKey,
93
+ wrappedTeamVaultKey: encode(crypto.crypto_box_seal(teamVaultKey, publicKey))
94
+ };
95
+ }
96
+ async function openTeamVaultGrant(grant, recipientPrivateKey) {
97
+ const crypto = await ready();
98
+ if (grant.version !== SERVICE_VAULT_ENCRYPTION_VERSION || grant.algorithm !== SERVICE_VAULT_KEY_AGREEMENT)
99
+ throw new Error("Team vault grant is unsupported.");
100
+ const publicKey = validKey(decode(grant.recipientPublicKey), crypto.crypto_box_PUBLICKEYBYTES, "Recipient public key");
101
+ validKey(recipientPrivateKey, crypto.crypto_box_SECRETKEYBYTES, "Recipient private key");
102
+ try {
103
+ return validKey(
104
+ crypto.crypto_box_seal_open(decode(grant.wrappedTeamVaultKey), publicKey, recipientPrivateKey),
105
+ crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
106
+ "Unwrapped team vault key"
107
+ );
108
+ } catch {
109
+ throw new Error("Team vault grant cannot be opened by this user key.");
110
+ }
111
+ }
112
+ async function encryptServiceCredential(plaintext, teamVaultKey, associatedData) {
113
+ const crypto = await ready();
114
+ validKey(teamVaultKey, crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "Team vault key");
115
+ if (!plaintext || !associatedData) throw new Error("Credential value and associated data are required.");
116
+ const dataKey = crypto.crypto_aead_xchacha20poly1305_ietf_keygen();
117
+ const nonce = crypto.randombytes_buf(crypto.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
118
+ const wrappedKeyNonce = crypto.randombytes_buf(crypto.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
119
+ try {
120
+ return {
121
+ version: SERVICE_VAULT_ENCRYPTION_VERSION,
122
+ algorithm: SERVICE_VAULT_AEAD_ALGORITHM,
123
+ ciphertext: encode(crypto.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, associatedData, null, nonce, dataKey)),
124
+ nonce: encode(nonce),
125
+ wrappedKey: encode(crypto.crypto_aead_xchacha20poly1305_ietf_encrypt(dataKey, associatedData, null, wrappedKeyNonce, teamVaultKey)),
126
+ wrappedKeyNonce: encode(wrappedKeyNonce),
127
+ associatedData,
128
+ associatedDataDigest: hash(associatedData),
129
+ fingerprint: hash(plaintext, teamVaultKey)
130
+ };
131
+ } finally {
132
+ crypto.memzero(dataKey);
133
+ }
134
+ }
135
+ async function decryptServiceCredential(envelope, teamVaultKey, expectedAssociatedData) {
136
+ const crypto = await ready();
137
+ validKey(teamVaultKey, crypto.crypto_aead_xchacha20poly1305_ietf_KEYBYTES, "Team vault key");
138
+ if (envelope.version !== SERVICE_VAULT_ENCRYPTION_VERSION || envelope.algorithm !== SERVICE_VAULT_AEAD_ALGORITHM || envelope.associatedData !== expectedAssociatedData || envelope.associatedDataDigest !== hash(expectedAssociatedData))
139
+ throw new Error("Credential envelope binding is invalid.");
140
+ let dataKey;
141
+ try {
142
+ dataKey = crypto.crypto_aead_xchacha20poly1305_ietf_decrypt(
143
+ null,
144
+ decode(envelope.wrappedKey),
145
+ expectedAssociatedData,
146
+ decode(envelope.wrappedKeyNonce),
147
+ teamVaultKey
148
+ );
149
+ return crypto.crypto_aead_xchacha20poly1305_ietf_decrypt(
150
+ null,
151
+ decode(envelope.ciphertext),
152
+ expectedAssociatedData,
153
+ decode(envelope.nonce),
154
+ dataKey,
155
+ "text"
156
+ );
157
+ } catch {
158
+ throw new Error("Credential envelope cannot be decrypted.");
159
+ } finally {
160
+ if (dataKey) crypto.memzero(dataKey);
161
+ }
162
+ }
163
+ async function rewrapServiceCredential(envelope, currentTeamVaultKey, replacementTeamVaultKey) {
164
+ const plaintext = await decryptServiceCredential(envelope, currentTeamVaultKey, envelope.associatedData);
165
+ return encryptServiceCredential(plaintext, replacementTeamVaultKey, envelope.associatedData);
166
+ }
167
+ async function sealSecretOperationPayload(values, operationPublicKey) {
168
+ const crypto = await ready();
169
+ if (!Object.keys(values).length || Object.values(values).some((value) => typeof value !== "string" || !value))
170
+ throw new Error("Secret operation payload must contain only non-empty string values.");
171
+ const payload = JSON.stringify(Object.fromEntries(Object.entries(values).sort(([left], [right]) => left.localeCompare(right))));
172
+ return encode(crypto.crypto_box_seal(payload, validKey(decode(operationPublicKey), crypto.crypto_box_PUBLICKEYBYTES, "Operation public key")));
173
+ }
174
+ async function encryptGitHubActionsSecret(value, providerPublicKey) {
175
+ const crypto = await ready();
176
+ if (!value) throw new Error("GitHub Actions secret value is required.");
177
+ return encode(crypto.crypto_box_seal(
178
+ value,
179
+ validKey(decode(providerPublicKey), crypto.crypto_box_PUBLICKEYBYTES, "GitHub public key")
180
+ ));
181
+ }
182
+ async function openSecretOperationPayload(sealedPayload, operationPublicKey, operationPrivateKey) {
183
+ const crypto = await ready();
184
+ try {
185
+ const plaintext = crypto.crypto_box_seal_open(decode(sealedPayload), decode(operationPublicKey), operationPrivateKey, "text");
186
+ const parsed = JSON.parse(plaintext);
187
+ if (!parsed || Array.isArray(parsed) || Object.values(parsed).some((value) => typeof value !== "string" || !value)) throw new Error();
188
+ return parsed;
189
+ } catch {
190
+ throw new Error("Secret operation payload cannot be opened.");
191
+ }
192
+ }
193
+ function clearServiceVaultKey(value) {
194
+ value?.fill(0);
195
+ }
196
+ export {
197
+ clearServiceVaultKey,
198
+ createServiceVaultKey,
199
+ createServiceVaultUserKeyPair,
200
+ createTeamVaultGrant,
201
+ decryptServiceCredential,
202
+ decryptServiceVaultPrivateKey,
203
+ encryptGitHubActionsSecret,
204
+ encryptServiceCredential,
205
+ encryptServiceVaultPrivateKey,
206
+ openSecretOperationPayload,
207
+ openTeamVaultGrant,
208
+ rewrapServiceCredential,
209
+ sealSecretOperationPayload
210
+ };
@@ -184,5 +184,4 @@ export interface AgentActivityPlanningIntent {
184
184
  signals?: AgentSignalPolicy;
185
185
  }>;
186
186
  requiresArtifactKinds?: string[];
187
- proposalTypes?: string[];
188
187
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.13.0-rc.81",
3
+ "version": "0.13.0-rc.83",
4
4
  "description": "Portable TreeSeed contracts, standards, and typed remote control-plane clients.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -53,6 +53,7 @@
53
53
  "dependencies": {
54
54
  "@treeseed/treedx": "0.3.0-rc.4",
55
55
  "esbuild": "^0.28.0",
56
+ "libsodium-wrappers-sumo": "0.8.4",
56
57
  "typescript": "^5.9.3",
57
58
  "yaml": "^2.8.1",
58
59
  "zod": "^3.25.76"