@treeseed/sdk 0.13.0-rc.71 → 0.13.0-rc.72
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/.treeseed-build-complete.json +1 -1
- package/dist/deployment/hosted-topology.d.ts +49 -0
- package/dist/deployment/hosted-topology.js +17 -1
- package/dist/operator-contracts/canonical-command-tree.js +10 -0
- package/dist/operator-contracts/catalog/hosted-topology-operations.d.ts +168 -0
- package/dist/operator-contracts/catalog/hosted-topology-operations.js +77 -0
- package/dist/operator-contracts/control-plane-operations.d.ts +170 -0
- package/dist/operator-contracts/control-plane-operations.js +3 -4
- package/dist/secrets-capability/service-provider-contracts.js +10 -9
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"completedAt":"2026-09-02T02:
|
|
1
|
+
{"completedAt":"2026-09-02T02:59:22.984Z"}
|
|
@@ -705,6 +705,7 @@ export declare const hostedTopologyRollbackSchema: z.ZodObject<{
|
|
|
705
705
|
schemaVersion: z.ZodLiteral<"treeseed.hosted-topology-rollback/v1">;
|
|
706
706
|
rollbackId: z.ZodString;
|
|
707
707
|
sourceReceiptId: z.ZodString;
|
|
708
|
+
environment: z.ZodEnum<["staging", "production"]>;
|
|
708
709
|
operations: z.ZodArray<z.ZodObject<{
|
|
709
710
|
resourceId: z.ZodString;
|
|
710
711
|
action: z.ZodEnum<["restore", "delete-created", "noop"]>;
|
|
@@ -724,6 +725,7 @@ export declare const hostedTopologyRollbackSchema: z.ZodObject<{
|
|
|
724
725
|
rollbackDigest: z.ZodString;
|
|
725
726
|
}, "strict", z.ZodTypeAny, {
|
|
726
727
|
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
728
|
+
environment: "production" | "staging";
|
|
727
729
|
operations: {
|
|
728
730
|
action: "noop" | "restore" | "delete-created";
|
|
729
731
|
resourceId: string;
|
|
@@ -735,6 +737,7 @@ export declare const hostedTopologyRollbackSchema: z.ZodObject<{
|
|
|
735
737
|
rollbackDigest: string;
|
|
736
738
|
}, {
|
|
737
739
|
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
740
|
+
environment: "production" | "staging";
|
|
738
741
|
operations: {
|
|
739
742
|
action: "noop" | "restore" | "delete-created";
|
|
740
743
|
resourceId: string;
|
|
@@ -745,6 +748,28 @@ export declare const hostedTopologyRollbackSchema: z.ZodObject<{
|
|
|
745
748
|
sourceReceiptId: string;
|
|
746
749
|
rollbackDigest: string;
|
|
747
750
|
}>;
|
|
751
|
+
export declare const hostedTopologyRollbackApprovalSchema: z.ZodObject<{
|
|
752
|
+
schemaVersion: z.ZodLiteral<"treeseed.hosted-topology-rollback-approval/v1">;
|
|
753
|
+
rollbackDigest: z.ZodString;
|
|
754
|
+
environment: z.ZodEnum<["staging", "production"]>;
|
|
755
|
+
decision: z.ZodLiteral<"approved">;
|
|
756
|
+
approvedBy: z.ZodString;
|
|
757
|
+
approvedAt: z.ZodString;
|
|
758
|
+
}, "strict", z.ZodTypeAny, {
|
|
759
|
+
schemaVersion: "treeseed.hosted-topology-rollback-approval/v1";
|
|
760
|
+
environment: "production" | "staging";
|
|
761
|
+
decision: "approved";
|
|
762
|
+
approvedBy: string;
|
|
763
|
+
approvedAt: string;
|
|
764
|
+
rollbackDigest: string;
|
|
765
|
+
}, {
|
|
766
|
+
schemaVersion: "treeseed.hosted-topology-rollback-approval/v1";
|
|
767
|
+
environment: "production" | "staging";
|
|
768
|
+
decision: "approved";
|
|
769
|
+
approvedBy: string;
|
|
770
|
+
approvedAt: string;
|
|
771
|
+
rollbackDigest: string;
|
|
772
|
+
}>;
|
|
748
773
|
export type HostedTopologyDeclaration = z.infer<typeof hostedTopologyDeclarationSchema>;
|
|
749
774
|
export type HostedResourceObservation = z.infer<typeof hostedResourceObservationSchema>;
|
|
750
775
|
export type HostedTopologyPlan = z.infer<typeof hostedTopologyPlanSchema>;
|
|
@@ -765,6 +790,7 @@ export declare function verifyHostedTopologyReadback(input: {
|
|
|
765
790
|
}): HostedTopologyReceipt;
|
|
766
791
|
export declare function planHostedTopologyRollback(receiptInput: HostedTopologyReceipt): {
|
|
767
792
|
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
793
|
+
environment: "production" | "staging";
|
|
768
794
|
operations: {
|
|
769
795
|
action: "noop" | "restore" | "delete-created";
|
|
770
796
|
resourceId: string;
|
|
@@ -775,3 +801,26 @@ export declare function planHostedTopologyRollback(receiptInput: HostedTopologyR
|
|
|
775
801
|
sourceReceiptId: string;
|
|
776
802
|
rollbackDigest: string;
|
|
777
803
|
};
|
|
804
|
+
export declare function authorizeHostedTopologyRollback(rollbackInput: z.input<typeof hostedTopologyRollbackSchema>, approvalInput: z.input<typeof hostedTopologyRollbackApprovalSchema>): {
|
|
805
|
+
rollback: {
|
|
806
|
+
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
807
|
+
environment: "production" | "staging";
|
|
808
|
+
operations: {
|
|
809
|
+
action: "noop" | "restore" | "delete-created";
|
|
810
|
+
resourceId: string;
|
|
811
|
+
providerResourceId: string;
|
|
812
|
+
targetDigest: string | null;
|
|
813
|
+
}[];
|
|
814
|
+
rollbackId: string;
|
|
815
|
+
sourceReceiptId: string;
|
|
816
|
+
rollbackDigest: string;
|
|
817
|
+
};
|
|
818
|
+
approval: {
|
|
819
|
+
schemaVersion: "treeseed.hosted-topology-rollback-approval/v1";
|
|
820
|
+
environment: "production" | "staging";
|
|
821
|
+
decision: "approved";
|
|
822
|
+
approvedBy: string;
|
|
823
|
+
approvedAt: string;
|
|
824
|
+
rollbackDigest: string;
|
|
825
|
+
};
|
|
826
|
+
};
|
|
@@ -113,6 +113,7 @@ const hostedTopologyRollbackSchema = z.object({
|
|
|
113
113
|
schemaVersion: z.literal("treeseed.hosted-topology-rollback/v1"),
|
|
114
114
|
rollbackId: z.string().regex(/^topology-rollback-[a-f0-9]{16}$/u),
|
|
115
115
|
sourceReceiptId: z.string().regex(/^topology-receipt-[a-f0-9]{16}$/u),
|
|
116
|
+
environment: z.enum(["staging", "production"]),
|
|
116
117
|
operations: z.array(z.object({
|
|
117
118
|
resourceId: identifier,
|
|
118
119
|
action: z.enum(["restore", "delete-created", "noop"]),
|
|
@@ -121,6 +122,14 @@ const hostedTopologyRollbackSchema = z.object({
|
|
|
121
122
|
}).strict()),
|
|
122
123
|
rollbackDigest: digest
|
|
123
124
|
}).strict();
|
|
125
|
+
const hostedTopologyRollbackApprovalSchema = z.object({
|
|
126
|
+
schemaVersion: z.literal("treeseed.hosted-topology-rollback-approval/v1"),
|
|
127
|
+
rollbackDigest: digest,
|
|
128
|
+
environment: z.enum(["staging", "production"]),
|
|
129
|
+
decision: z.literal("approved"),
|
|
130
|
+
approvedBy: z.string().min(1).max(256),
|
|
131
|
+
approvedAt: timestamp
|
|
132
|
+
}).strict();
|
|
124
133
|
function observationMap(items, declaration) {
|
|
125
134
|
const resources = new Map(declaration.resources.map((resource) => [resource.id, resource]));
|
|
126
135
|
const observations = /* @__PURE__ */ new Map();
|
|
@@ -211,10 +220,16 @@ function planHostedTopologyRollback(receiptInput) {
|
|
|
211
220
|
return { resourceId: resource.resourceId, action: !prior || prior.state === "missing" ? "delete-created" : prior.observedDigest === resource.observedDigest ? "noop" : "restore", providerResourceId: resource.providerResourceId, targetDigest: prior?.observedDigest ?? null };
|
|
212
221
|
}).sort((left, right) => left.resourceId.localeCompare(right.resourceId));
|
|
213
222
|
const rollbackDigest = deploymentDigest({ sourceReceiptId: receipt.receiptId, operations });
|
|
214
|
-
return hostedTopologyRollbackSchema.parse({ schemaVersion: "treeseed.hosted-topology-rollback/v1", rollbackId: `topology-rollback-${rollbackDigest.slice(7, 23)}`, sourceReceiptId: receipt.receiptId, operations, rollbackDigest });
|
|
223
|
+
return hostedTopologyRollbackSchema.parse({ schemaVersion: "treeseed.hosted-topology-rollback/v1", rollbackId: `topology-rollback-${rollbackDigest.slice(7, 23)}`, sourceReceiptId: receipt.receiptId, environment: receipt.environment, operations, rollbackDigest });
|
|
224
|
+
}
|
|
225
|
+
function authorizeHostedTopologyRollback(rollbackInput, approvalInput) {
|
|
226
|
+
const rollback = hostedTopologyRollbackSchema.parse(rollbackInput), approval = hostedTopologyRollbackApprovalSchema.parse(approvalInput);
|
|
227
|
+
if (approval.rollbackDigest !== rollback.rollbackDigest || approval.environment !== rollback.environment) throw new Error("Hosted topology rollback approval does not bind the exact rollback and environment.");
|
|
228
|
+
return { rollback, approval };
|
|
215
229
|
}
|
|
216
230
|
export {
|
|
217
231
|
authorizeHostedTopologyPlan,
|
|
232
|
+
authorizeHostedTopologyRollback,
|
|
218
233
|
authorizedHostedTopologyPlanSchema,
|
|
219
234
|
hostedProviderSchema,
|
|
220
235
|
hostedResourceKindSchema,
|
|
@@ -223,6 +238,7 @@ export {
|
|
|
223
238
|
hostedTopologyDeclarationSchema,
|
|
224
239
|
hostedTopologyPlanSchema,
|
|
225
240
|
hostedTopologyReceiptSchema,
|
|
241
|
+
hostedTopologyRollbackApprovalSchema,
|
|
226
242
|
hostedTopologyRollbackSchema,
|
|
227
243
|
planHostedTopology,
|
|
228
244
|
planHostedTopologyRollback,
|
|
@@ -34,6 +34,10 @@ const operationBindings = {
|
|
|
34
34
|
"platform verify": local("local.platform.verify"),
|
|
35
35
|
"platform workset": local("local.platform.workset"),
|
|
36
36
|
"platform project create": local("local.platform.project.create"),
|
|
37
|
+
"platform topology plan": local("local.platform.topology.plan"),
|
|
38
|
+
"platform topology apply": local("local.platform.topology.apply"),
|
|
39
|
+
"platform topology status": local("local.platform.topology.status"),
|
|
40
|
+
"platform topology rollback": local("local.platform.topology.rollback"),
|
|
37
41
|
"host status": local("local.host.status"),
|
|
38
42
|
"host doctor": local("local.host.doctor"),
|
|
39
43
|
"host plan": local("local.host.plan"),
|
|
@@ -358,6 +362,12 @@ const commandTree = {
|
|
|
358
362
|
{ nodeType: "leaf", segment: "workset", description: "Plan or safely materialize exact primary source checkouts beneath packages/.", kind: "mutation", options: [planOption, { name: "--apply", description: "Apply the frozen workset plan.", type: "boolean" }, { name: "--yes", description: "Confirm the planned checkout mutations.", type: "boolean" }, { name: "--profile", description: "Composable source profile; repeat to union profiles.", type: "string[]" }, { name: "--project", description: "Explicit project slug; repeat to select projects.", type: "string[]" }, { name: "--exclude", description: "Project slug to exclude; repeat as needed.", type: "string[]" }, { name: "--json", description: "Emit the stable command-result envelope.", type: "boolean" }], authorization: { capability: "development.workset", confirmation: "never" }, resultSchemaId: "treeseed.platform-workset-result/v1", execution: local("local.platform.workset") },
|
|
359
363
|
branch("project", [
|
|
360
364
|
{ nodeType: "leaf", segment: "create", description: "Plan or reconcile a project, repository, template, library binding, and live inventory without writing application source into Platform Git.", kind: "mutation", arguments: [{ name: "slug", description: "Portable project slug.", required: true }], options: [planOption, { name: "--apply", description: "Apply the accepted creation plan.", type: "boolean" }, { name: "--yes", description: "Confirm authority-bearing project creation.", type: "boolean" }, { name: "--template", description: "Published template identity.", type: "string", required: true }, { name: "--json", description: "Emit the stable command-result envelope.", type: "boolean" }], authorization: { capability: "projects.create", confirmation: "authority" }, resultSchemaId: "treeseed.platform-project-create-result/v1", execution: local("local.platform.project.create") }
|
|
365
|
+
]),
|
|
366
|
+
branch("topology", [
|
|
367
|
+
{ nodeType: "leaf", segment: "plan", description: "Plan Cloudflare and Railway reconciliation from a portable hosted-topology declaration.", kind: "read", arguments: [{ name: "file", description: "Hosted topology YAML or JSON declaration.", required: true }], resultSchemaId: "treeseed.hosted-topology-plan/v1", execution: local("local.platform.topology.plan") },
|
|
368
|
+
{ nodeType: "leaf", segment: "apply", description: "Apply an exact reviewed hosted-topology plan through the operations runner.", kind: "mutation", arguments: [{ name: "plan", description: "Exact plan JSON file.", required: true }], options: [planOption, { name: "--approval", description: "Exact environment approval JSON file.", type: "string", required: true }, { name: "--yes", description: "Confirm the authority-bearing mutation.", type: "boolean" }], authorization: { capability: "infrastructure.write", confirmation: "authority" }, resultSchemaId: "treeseed.platform-operation/v1", execution: local("local.platform.topology.apply") },
|
|
369
|
+
{ nodeType: "leaf", segment: "status", description: "Read the latest hosted-topology operation and known-good receipt.", kind: "read", resultSchemaId: "treeseed.infrastructure.topology.status.output/v1", execution: local("local.platform.topology.status") },
|
|
370
|
+
{ nodeType: "leaf", segment: "rollback", description: "Restore exact prior hosted-topology state from a known-good receipt.", kind: "mutation", arguments: [{ name: "rollback", description: "Exact rollback JSON file.", required: true }], options: [planOption, { name: "--approval", description: "Exact rollback approval JSON file.", type: "string", required: true }, { name: "--yes", description: "Confirm the destructive rollback.", type: "boolean" }], authorization: { capability: "infrastructure.write", confirmation: "destructive" }, resultSchemaId: "treeseed.platform-operation/v1", execution: local("local.platform.topology.rollback") }
|
|
361
371
|
])
|
|
362
372
|
]),
|
|
363
373
|
branch("dev", [
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export declare const HOSTED_TOPOLOGY_OPERATIONS: {
|
|
2
|
+
readonly plan: import("../control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
3
|
+
teamId: string;
|
|
4
|
+
}, {}, {
|
|
5
|
+
declaration: {
|
|
6
|
+
schemaVersion: "treeseed.hosted-topology/v1";
|
|
7
|
+
resources: {
|
|
8
|
+
id: string;
|
|
9
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
10
|
+
provider: "cloudflare" | "railway";
|
|
11
|
+
adoption: {
|
|
12
|
+
mode: "adopt-or-create";
|
|
13
|
+
replacement: "forbidden";
|
|
14
|
+
externalIdInput?: string | undefined;
|
|
15
|
+
};
|
|
16
|
+
dependsOn?: string[] | undefined;
|
|
17
|
+
parameters?: Record<string, {
|
|
18
|
+
input: string;
|
|
19
|
+
} | {
|
|
20
|
+
artifact: string;
|
|
21
|
+
} | {
|
|
22
|
+
resourceOutput: {
|
|
23
|
+
resourceId: string;
|
|
24
|
+
output: string;
|
|
25
|
+
};
|
|
26
|
+
} | {
|
|
27
|
+
literal: string | number | boolean;
|
|
28
|
+
}> | undefined;
|
|
29
|
+
}[];
|
|
30
|
+
id: string;
|
|
31
|
+
platform: {
|
|
32
|
+
repository: "treeseed-ai/platform";
|
|
33
|
+
commit: string;
|
|
34
|
+
};
|
|
35
|
+
mutation: "approval-required";
|
|
36
|
+
environment: "production" | "staging";
|
|
37
|
+
artifacts: Record<string, {
|
|
38
|
+
digest: string;
|
|
39
|
+
source: string;
|
|
40
|
+
}>;
|
|
41
|
+
providerConnections: Partial<Record<"cloudflare" | "railway", {
|
|
42
|
+
connectionRef: string;
|
|
43
|
+
}>>;
|
|
44
|
+
};
|
|
45
|
+
}, {
|
|
46
|
+
schemaVersion: "treeseed.hosted-topology-plan/v1";
|
|
47
|
+
blockers: {
|
|
48
|
+
code: "connection-unavailable" | "dependency-cycle" | "observation-unhealthy" | "adoption-drift";
|
|
49
|
+
message: string;
|
|
50
|
+
resourceId?: string | undefined;
|
|
51
|
+
}[];
|
|
52
|
+
planDigest: string;
|
|
53
|
+
actions: {
|
|
54
|
+
action: "noop" | "create" | "adopt" | "update";
|
|
55
|
+
resourceId: string;
|
|
56
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
57
|
+
provider: "cloudflare" | "railway";
|
|
58
|
+
providerResourceId: string | null;
|
|
59
|
+
desiredDigest: string;
|
|
60
|
+
previousDigest: string | null;
|
|
61
|
+
}[];
|
|
62
|
+
environment: "production" | "staging";
|
|
63
|
+
executable: false;
|
|
64
|
+
planId: string;
|
|
65
|
+
declarationDigest: string;
|
|
66
|
+
topologyId: string;
|
|
67
|
+
platformCommit: string;
|
|
68
|
+
approvalRequired: boolean;
|
|
69
|
+
}>;
|
|
70
|
+
readonly apply: import("../control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
71
|
+
teamId: string;
|
|
72
|
+
}, {}, {
|
|
73
|
+
approval: {
|
|
74
|
+
schemaVersion: "treeseed.hosted-topology-approval/v1";
|
|
75
|
+
planDigest: string;
|
|
76
|
+
environment: "production" | "staging";
|
|
77
|
+
decision: "approved";
|
|
78
|
+
approvedBy: string;
|
|
79
|
+
approvedAt: string;
|
|
80
|
+
};
|
|
81
|
+
plan: {
|
|
82
|
+
schemaVersion: "treeseed.hosted-topology-plan/v1";
|
|
83
|
+
blockers: {
|
|
84
|
+
code: "connection-unavailable" | "dependency-cycle" | "observation-unhealthy" | "adoption-drift";
|
|
85
|
+
message: string;
|
|
86
|
+
resourceId?: string | undefined;
|
|
87
|
+
}[];
|
|
88
|
+
planDigest: string;
|
|
89
|
+
actions: {
|
|
90
|
+
action: "noop" | "create" | "adopt" | "update";
|
|
91
|
+
resourceId: string;
|
|
92
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
93
|
+
provider: "cloudflare" | "railway";
|
|
94
|
+
providerResourceId: string | null;
|
|
95
|
+
desiredDigest: string;
|
|
96
|
+
previousDigest: string | null;
|
|
97
|
+
}[];
|
|
98
|
+
environment: "production" | "staging";
|
|
99
|
+
executable: false;
|
|
100
|
+
planId: string;
|
|
101
|
+
declarationDigest: string;
|
|
102
|
+
topologyId: string;
|
|
103
|
+
platformCommit: string;
|
|
104
|
+
approvalRequired: boolean;
|
|
105
|
+
};
|
|
106
|
+
}, Record<string, unknown>>;
|
|
107
|
+
readonly status: import("../control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
108
|
+
teamId: string;
|
|
109
|
+
}, {}, undefined, {
|
|
110
|
+
operation: Record<string, unknown> | null;
|
|
111
|
+
receipt: {
|
|
112
|
+
schemaVersion: "treeseed.hosted-topology-receipt/v1";
|
|
113
|
+
resources: {
|
|
114
|
+
state: "missing" | "degraded" | "healthy";
|
|
115
|
+
resourceId: string;
|
|
116
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
117
|
+
provider: "cloudflare" | "railway";
|
|
118
|
+
providerResourceId: string | null;
|
|
119
|
+
managedBy: "external" | "treeseed" | null;
|
|
120
|
+
observedDigest: string | null;
|
|
121
|
+
observedAt: string;
|
|
122
|
+
}[];
|
|
123
|
+
planDigest: string;
|
|
124
|
+
state: "known-good";
|
|
125
|
+
environment: "production" | "staging";
|
|
126
|
+
completedAt: string;
|
|
127
|
+
receiptId: string;
|
|
128
|
+
declarationDigest: string;
|
|
129
|
+
topologyId: string;
|
|
130
|
+
platformCommit: string;
|
|
131
|
+
previousResources: {
|
|
132
|
+
state: "missing" | "degraded" | "healthy";
|
|
133
|
+
resourceId: string;
|
|
134
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
135
|
+
provider: "cloudflare" | "railway";
|
|
136
|
+
providerResourceId: string | null;
|
|
137
|
+
managedBy: "external" | "treeseed" | null;
|
|
138
|
+
observedDigest: string | null;
|
|
139
|
+
observedAt: string;
|
|
140
|
+
}[];
|
|
141
|
+
} | null;
|
|
142
|
+
}>;
|
|
143
|
+
readonly rollback: import("../control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
144
|
+
teamId: string;
|
|
145
|
+
}, {}, {
|
|
146
|
+
rollback: {
|
|
147
|
+
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
148
|
+
environment: "production" | "staging";
|
|
149
|
+
operations: {
|
|
150
|
+
action: "noop" | "restore" | "delete-created";
|
|
151
|
+
resourceId: string;
|
|
152
|
+
providerResourceId: string;
|
|
153
|
+
targetDigest: string | null;
|
|
154
|
+
}[];
|
|
155
|
+
rollbackId: string;
|
|
156
|
+
sourceReceiptId: string;
|
|
157
|
+
rollbackDigest: string;
|
|
158
|
+
};
|
|
159
|
+
approval: {
|
|
160
|
+
schemaVersion: "treeseed.hosted-topology-rollback-approval/v1";
|
|
161
|
+
environment: "production" | "staging";
|
|
162
|
+
decision: "approved";
|
|
163
|
+
approvedBy: string;
|
|
164
|
+
approvedAt: string;
|
|
165
|
+
rollbackDigest: string;
|
|
166
|
+
};
|
|
167
|
+
}, Record<string, unknown>>;
|
|
168
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hostedTopologyApprovalSchema, hostedTopologyDeclarationSchema, hostedTopologyPlanSchema, hostedTopologyReceiptSchema, hostedTopologyRollbackApprovalSchema, hostedTopologyRollbackSchema } from "../../deployment/hosted-topology.js";
|
|
3
|
+
import { defineOperation } from "../operation-builder.js";
|
|
4
|
+
const teamPath = z.object({ teamId: z.string().min(1) }).strict();
|
|
5
|
+
const empty = z.object({}).strict();
|
|
6
|
+
const none = z.undefined();
|
|
7
|
+
const operationReceipt = z.record(z.unknown());
|
|
8
|
+
const HOSTED_TOPOLOGY_OPERATIONS = {
|
|
9
|
+
plan: defineOperation({
|
|
10
|
+
operationId: "infrastructure.topology.plan",
|
|
11
|
+
description: "Plan exact hosted topology reconciliation from authoritative provider observations.",
|
|
12
|
+
rest: { method: "POST", path: "/v1/teams/{teamId}/infrastructure/topology/plan" },
|
|
13
|
+
parameters: "treeseed.infrastructure.topology.plan.parameters/v1",
|
|
14
|
+
capability: "infrastructure.read",
|
|
15
|
+
authentication: "oauth",
|
|
16
|
+
oauthScopes: ["treeseed:read"],
|
|
17
|
+
kind: "read",
|
|
18
|
+
riskClass: "ordinary",
|
|
19
|
+
confirmation: "never",
|
|
20
|
+
surfaces: ["rest", "cli"],
|
|
21
|
+
cacheScope: "none",
|
|
22
|
+
pagination: "none",
|
|
23
|
+
idempotencyRequired: false
|
|
24
|
+
}, { path: teamPath, query: empty, body: z.object({ declaration: hostedTopologyDeclarationSchema }).strict(), output: hostedTopologyPlanSchema }),
|
|
25
|
+
apply: defineOperation({
|
|
26
|
+
operationId: "infrastructure.topology.apply",
|
|
27
|
+
description: "Apply an exact approved hosted topology plan through the operations runner.",
|
|
28
|
+
rest: { method: "POST", path: "/v1/teams/{teamId}/infrastructure/topology/apply" },
|
|
29
|
+
parameters: "treeseed.infrastructure.topology.apply.parameters/v1",
|
|
30
|
+
capability: "infrastructure.write",
|
|
31
|
+
authentication: "oauth",
|
|
32
|
+
oauthScopes: ["treeseed:admin"],
|
|
33
|
+
kind: "mutation",
|
|
34
|
+
riskClass: "authority",
|
|
35
|
+
confirmation: "input_required",
|
|
36
|
+
surfaces: ["rest", "cli"],
|
|
37
|
+
cacheScope: "none",
|
|
38
|
+
pagination: "none",
|
|
39
|
+
concurrencyRequired: true,
|
|
40
|
+
redactedPaths: ["body.approval.approvedBy"]
|
|
41
|
+
}, { path: teamPath, query: empty, body: z.object({ plan: hostedTopologyPlanSchema, approval: hostedTopologyApprovalSchema }).strict(), output: operationReceipt }),
|
|
42
|
+
status: defineOperation({
|
|
43
|
+
operationId: "infrastructure.topology.status",
|
|
44
|
+
description: "Read the latest authoritative hosted topology receipt and operation state.",
|
|
45
|
+
rest: { method: "GET", path: "/v1/teams/{teamId}/infrastructure/topology" },
|
|
46
|
+
parameters: "treeseed.infrastructure.topology.status.parameters/v1",
|
|
47
|
+
capability: "infrastructure.read",
|
|
48
|
+
authentication: "oauth",
|
|
49
|
+
oauthScopes: ["treeseed:read"],
|
|
50
|
+
kind: "read",
|
|
51
|
+
riskClass: "ordinary",
|
|
52
|
+
confirmation: "never",
|
|
53
|
+
surfaces: ["rest", "cli"],
|
|
54
|
+
cacheScope: "principal",
|
|
55
|
+
pagination: "none"
|
|
56
|
+
}, { path: teamPath, query: empty, body: none, output: z.object({ receipt: hostedTopologyReceiptSchema.nullable(), operation: operationReceipt.nullable() }).strict() }),
|
|
57
|
+
rollback: defineOperation({
|
|
58
|
+
operationId: "infrastructure.topology.rollback",
|
|
59
|
+
description: "Restore exact prior hosted topology lineage from a known-good receipt.",
|
|
60
|
+
rest: { method: "POST", path: "/v1/teams/{teamId}/infrastructure/topology/rollback" },
|
|
61
|
+
parameters: "treeseed.infrastructure.topology.rollback.parameters/v1",
|
|
62
|
+
capability: "infrastructure.write",
|
|
63
|
+
authentication: "oauth",
|
|
64
|
+
oauthScopes: ["treeseed:admin"],
|
|
65
|
+
kind: "mutation",
|
|
66
|
+
riskClass: "destructive",
|
|
67
|
+
confirmation: "input_required",
|
|
68
|
+
surfaces: ["rest", "cli"],
|
|
69
|
+
cacheScope: "none",
|
|
70
|
+
pagination: "none",
|
|
71
|
+
concurrencyRequired: true,
|
|
72
|
+
redactedPaths: ["body.approval.approvedBy"]
|
|
73
|
+
}, { path: teamPath, query: empty, body: z.object({ rollback: hostedTopologyRollbackSchema, approval: hostedTopologyRollbackApprovalSchema }).strict(), output: operationReceipt })
|
|
74
|
+
};
|
|
75
|
+
export {
|
|
76
|
+
HOSTED_TOPOLOGY_OPERATIONS
|
|
77
|
+
};
|
|
@@ -1,5 +1,175 @@
|
|
|
1
1
|
import type { ControlPlaneOperationDescriptor } from './control-plane-operation.js';
|
|
2
2
|
export declare const CONTROL_PLANE_OPERATIONS: {
|
|
3
|
+
readonly infrastructure: {
|
|
4
|
+
readonly topology: {
|
|
5
|
+
readonly plan: import("./control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
6
|
+
teamId: string;
|
|
7
|
+
}, {}, {
|
|
8
|
+
declaration: {
|
|
9
|
+
schemaVersion: "treeseed.hosted-topology/v1";
|
|
10
|
+
resources: {
|
|
11
|
+
id: string;
|
|
12
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
13
|
+
provider: "cloudflare" | "railway";
|
|
14
|
+
adoption: {
|
|
15
|
+
mode: "adopt-or-create";
|
|
16
|
+
replacement: "forbidden";
|
|
17
|
+
externalIdInput?: string | undefined;
|
|
18
|
+
};
|
|
19
|
+
dependsOn?: string[] | undefined;
|
|
20
|
+
parameters?: Record<string, {
|
|
21
|
+
input: string;
|
|
22
|
+
} | {
|
|
23
|
+
artifact: string;
|
|
24
|
+
} | {
|
|
25
|
+
resourceOutput: {
|
|
26
|
+
resourceId: string;
|
|
27
|
+
output: string;
|
|
28
|
+
};
|
|
29
|
+
} | {
|
|
30
|
+
literal: string | number | boolean;
|
|
31
|
+
}> | undefined;
|
|
32
|
+
}[];
|
|
33
|
+
id: string;
|
|
34
|
+
platform: {
|
|
35
|
+
repository: "treeseed-ai/platform";
|
|
36
|
+
commit: string;
|
|
37
|
+
};
|
|
38
|
+
mutation: "approval-required";
|
|
39
|
+
environment: "production" | "staging";
|
|
40
|
+
artifacts: Record<string, {
|
|
41
|
+
digest: string;
|
|
42
|
+
source: string;
|
|
43
|
+
}>;
|
|
44
|
+
providerConnections: Partial<Record<"cloudflare" | "railway", {
|
|
45
|
+
connectionRef: string;
|
|
46
|
+
}>>;
|
|
47
|
+
};
|
|
48
|
+
}, {
|
|
49
|
+
schemaVersion: "treeseed.hosted-topology-plan/v1";
|
|
50
|
+
blockers: {
|
|
51
|
+
code: "connection-unavailable" | "dependency-cycle" | "observation-unhealthy" | "adoption-drift";
|
|
52
|
+
message: string;
|
|
53
|
+
resourceId?: string | undefined;
|
|
54
|
+
}[];
|
|
55
|
+
planDigest: string;
|
|
56
|
+
actions: {
|
|
57
|
+
action: "noop" | "create" | "adopt" | "update";
|
|
58
|
+
resourceId: string;
|
|
59
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
60
|
+
provider: "cloudflare" | "railway";
|
|
61
|
+
providerResourceId: string | null;
|
|
62
|
+
desiredDigest: string;
|
|
63
|
+
previousDigest: string | null;
|
|
64
|
+
}[];
|
|
65
|
+
environment: "production" | "staging";
|
|
66
|
+
executable: false;
|
|
67
|
+
planId: string;
|
|
68
|
+
declarationDigest: string;
|
|
69
|
+
topologyId: string;
|
|
70
|
+
platformCommit: string;
|
|
71
|
+
approvalRequired: boolean;
|
|
72
|
+
}>;
|
|
73
|
+
readonly apply: import("./control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
74
|
+
teamId: string;
|
|
75
|
+
}, {}, {
|
|
76
|
+
approval: {
|
|
77
|
+
schemaVersion: "treeseed.hosted-topology-approval/v1";
|
|
78
|
+
planDigest: string;
|
|
79
|
+
environment: "production" | "staging";
|
|
80
|
+
decision: "approved";
|
|
81
|
+
approvedBy: string;
|
|
82
|
+
approvedAt: string;
|
|
83
|
+
};
|
|
84
|
+
plan: {
|
|
85
|
+
schemaVersion: "treeseed.hosted-topology-plan/v1";
|
|
86
|
+
blockers: {
|
|
87
|
+
code: "connection-unavailable" | "dependency-cycle" | "observation-unhealthy" | "adoption-drift";
|
|
88
|
+
message: string;
|
|
89
|
+
resourceId?: string | undefined;
|
|
90
|
+
}[];
|
|
91
|
+
planDigest: string;
|
|
92
|
+
actions: {
|
|
93
|
+
action: "noop" | "create" | "adopt" | "update";
|
|
94
|
+
resourceId: string;
|
|
95
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
96
|
+
provider: "cloudflare" | "railway";
|
|
97
|
+
providerResourceId: string | null;
|
|
98
|
+
desiredDigest: string;
|
|
99
|
+
previousDigest: string | null;
|
|
100
|
+
}[];
|
|
101
|
+
environment: "production" | "staging";
|
|
102
|
+
executable: false;
|
|
103
|
+
planId: string;
|
|
104
|
+
declarationDigest: string;
|
|
105
|
+
topologyId: string;
|
|
106
|
+
platformCommit: string;
|
|
107
|
+
approvalRequired: boolean;
|
|
108
|
+
};
|
|
109
|
+
}, Record<string, unknown>>;
|
|
110
|
+
readonly status: import("./control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
111
|
+
teamId: string;
|
|
112
|
+
}, {}, undefined, {
|
|
113
|
+
operation: Record<string, unknown> | null;
|
|
114
|
+
receipt: {
|
|
115
|
+
schemaVersion: "treeseed.hosted-topology-receipt/v1";
|
|
116
|
+
resources: {
|
|
117
|
+
state: "missing" | "degraded" | "healthy";
|
|
118
|
+
resourceId: string;
|
|
119
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
120
|
+
provider: "cloudflare" | "railway";
|
|
121
|
+
providerResourceId: string | null;
|
|
122
|
+
managedBy: "external" | "treeseed" | null;
|
|
123
|
+
observedDigest: string | null;
|
|
124
|
+
observedAt: string;
|
|
125
|
+
}[];
|
|
126
|
+
planDigest: string;
|
|
127
|
+
state: "known-good";
|
|
128
|
+
environment: "production" | "staging";
|
|
129
|
+
completedAt: string;
|
|
130
|
+
receiptId: string;
|
|
131
|
+
declarationDigest: string;
|
|
132
|
+
topologyId: string;
|
|
133
|
+
platformCommit: string;
|
|
134
|
+
previousResources: {
|
|
135
|
+
state: "missing" | "degraded" | "healthy";
|
|
136
|
+
resourceId: string;
|
|
137
|
+
kind: "admin-application" | "dns-record" | "tls-policy" | "api-proxy" | "control-plane-api" | "postgresql" | "operations-runner" | "treedx-service";
|
|
138
|
+
provider: "cloudflare" | "railway";
|
|
139
|
+
providerResourceId: string | null;
|
|
140
|
+
managedBy: "external" | "treeseed" | null;
|
|
141
|
+
observedDigest: string | null;
|
|
142
|
+
observedAt: string;
|
|
143
|
+
}[];
|
|
144
|
+
} | null;
|
|
145
|
+
}>;
|
|
146
|
+
readonly rollback: import("./control-plane-operation.js").ControlPlaneOperationBinding<{
|
|
147
|
+
teamId: string;
|
|
148
|
+
}, {}, {
|
|
149
|
+
rollback: {
|
|
150
|
+
schemaVersion: "treeseed.hosted-topology-rollback/v1";
|
|
151
|
+
environment: "production" | "staging";
|
|
152
|
+
operations: {
|
|
153
|
+
action: "noop" | "restore" | "delete-created";
|
|
154
|
+
resourceId: string;
|
|
155
|
+
providerResourceId: string;
|
|
156
|
+
targetDigest: string | null;
|
|
157
|
+
}[];
|
|
158
|
+
rollbackId: string;
|
|
159
|
+
sourceReceiptId: string;
|
|
160
|
+
rollbackDigest: string;
|
|
161
|
+
};
|
|
162
|
+
approval: {
|
|
163
|
+
schemaVersion: "treeseed.hosted-topology-rollback-approval/v1";
|
|
164
|
+
environment: "production" | "staging";
|
|
165
|
+
decision: "approved";
|
|
166
|
+
approvedBy: string;
|
|
167
|
+
approvedAt: string;
|
|
168
|
+
rollbackDigest: string;
|
|
169
|
+
};
|
|
170
|
+
}, Record<string, unknown>>;
|
|
171
|
+
};
|
|
172
|
+
};
|
|
3
173
|
readonly capabilities: {
|
|
4
174
|
list: import("./control-plane-operation.js").ControlPlaneOperationBinding<{}, {
|
|
5
175
|
status?: "revoked" | "active" | "deprecated" | undefined;
|
|
@@ -7,11 +7,9 @@ import { TREEAI_CONTROL_PLANE_OPERATIONS } from "./catalog/treeai-operations.js"
|
|
|
7
7
|
import { capabilityOntologyOperations } from "./catalog/capability-ontology-operations.js";
|
|
8
8
|
import { knowledgeShareOperations } from "./catalog/knowledge-share-operations.js";
|
|
9
9
|
import { PROVIDER_ENVIRONMENT_OPERATIONS } from "./catalog/provider-environment-operations.js";
|
|
10
|
+
import { HOSTED_TOPOLOGY_OPERATIONS } from "./catalog/hosted-topology-operations.js";
|
|
10
11
|
import { buildControlPlaneCatalog, flattenControlPlaneOperations } from "./catalog/control-plane-catalog.js";
|
|
11
|
-
const empty = z.object({}).strict();
|
|
12
|
-
const none = z.undefined();
|
|
13
|
-
const record = z.record(z.unknown());
|
|
14
|
-
const payload = record;
|
|
12
|
+
const empty = z.object({}).strict(), none = z.undefined(), record = z.record(z.unknown()), payload = record;
|
|
15
13
|
function read(operationId, path, capability, surfaces = ["rest"]) {
|
|
16
14
|
return define({
|
|
17
15
|
operationId,
|
|
@@ -102,6 +100,7 @@ function resource(operationId, method, path, pathShape, options = { capability:
|
|
|
102
100
|
}, { path: z.object(pathShape).strict(), query: kind === "read" ? record : empty, body: kind === "read" ? none : record, output: payload });
|
|
103
101
|
}
|
|
104
102
|
const CONTROL_PLANE_OPERATIONS = {
|
|
103
|
+
infrastructure: { topology: HOSTED_TOPOLOGY_OPERATIONS },
|
|
105
104
|
capabilities: capabilityOntologyOperations(),
|
|
106
105
|
inbox: inboxOperations(),
|
|
107
106
|
treeai: TREEAI_CONTROL_PLANE_OPERATIONS,
|
|
@@ -117,14 +117,14 @@ const SERVICE_PROVIDER_CATALOG = [
|
|
|
117
117
|
knowledgePageIds: ["provider.cloudflare"],
|
|
118
118
|
connectionFields: [field("accountId", "Account ID", "The non-secret Cloudflare account identifier.")],
|
|
119
119
|
capabilities: [
|
|
120
|
-
{ type: "frontend-hosting", label: "Frontend hosting", description: "
|
|
121
|
-
{ type: "dns-management", label: "DNS management", description: "
|
|
120
|
+
{ type: "frontend-hosting", label: "Frontend hosting", description: "Pages and Workers application hosting.", credentialProfileIds: ["cloudflare-runtime"], status: "available" },
|
|
121
|
+
{ type: "dns-management", label: "DNS management", description: "Scoped DNS record management.", credentialProfileIds: ["cloudflare-dns"], status: "available" },
|
|
122
122
|
{ type: "object-storage", label: "Object storage", description: "R2-backed immutable publication and private artifact storage.", credentialProfileIds: ["cloudflare-storage"], status: "available" }
|
|
123
123
|
],
|
|
124
124
|
credentialProfiles: [
|
|
125
|
-
{ 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:
|
|
126
|
-
{ 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:
|
|
127
|
-
{ id: "cloudflare-storage", label: "Storage token", description: "A token limited to R2 resources.", capabilities: ["object-storage"], fields: [field("apiToken", "Storage API token", "Encrypted separately from runtime and DNS authority.", true, true)], permissions: ["Account: Workers R2 Storage Edit"], sharing: "capability-scoped", unattendedCompatible:
|
|
125
|
+
{ 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"] },
|
|
126
|
+
{ 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"] },
|
|
127
|
+
{ id: "cloudflare-storage", label: "Storage token", description: "A token limited to R2 resources.", capabilities: ["object-storage"], fields: [field("apiToken", "Storage API token", "Encrypted separately from runtime and DNS authority.", true, true)], permissions: ["Account: Workers R2 Storage Edit"], sharing: "capability-scoped", unattendedCompatible: true, authoritySchemes: ["environment-reference", "external-vault", "workload-identity"], knowledgePageIds: ["provider.cloudflare", "services.credentials", "vault.rotation"] }
|
|
128
128
|
]
|
|
129
129
|
},
|
|
130
130
|
{
|
|
@@ -136,10 +136,10 @@ const SERVICE_PROVIDER_CATALOG = [
|
|
|
136
136
|
knowledgePageIds: ["provider.railway"],
|
|
137
137
|
connectionFields: [field("workspaceId", "Workspace ID", "The non-secret Railway workspace identifier.")],
|
|
138
138
|
capabilities: [
|
|
139
|
-
{ type: "backend-hosting", label: "Backend hosting", description: "
|
|
140
|
-
{ type: "database-hosting", label: "Database hosting", description: "
|
|
139
|
+
{ type: "backend-hosting", label: "Backend hosting", description: "API and backend service hosting.", credentialProfileIds: ["railway-workspace"], status: "available" },
|
|
140
|
+
{ type: "database-hosting", label: "Database hosting", description: "Managed database placement.", credentialProfileIds: ["railway-workspace"], status: "available" },
|
|
141
141
|
{ type: "capacity-runtime-hosting", label: "Capacity runtime hosting", description: "Future capacity provider placement.", credentialProfileIds: ["railway-workspace"], status: "planned" },
|
|
142
|
-
{ type: "private-knowledge-index-hosting", label: "Private knowledge hosting", description: "
|
|
142
|
+
{ type: "private-knowledge-index-hosting", label: "Private knowledge hosting", description: "Private TreeDX knowledge-plane placement.", credentialProfileIds: ["railway-workspace"], status: "available" }
|
|
143
143
|
],
|
|
144
144
|
credentialProfiles: [{
|
|
145
145
|
id: "railway-workspace",
|
|
@@ -149,7 +149,8 @@ const SERVICE_PROVIDER_CATALOG = [
|
|
|
149
149
|
fields: [field("apiToken", "Workspace token", "Encrypted in this browser. TreeSeed will request explicit authorization before interactive use.", true, true)],
|
|
150
150
|
permissions: ["Workspace access required by the selected operations"],
|
|
151
151
|
sharing: "provider-shared",
|
|
152
|
-
unattendedCompatible:
|
|
152
|
+
unattendedCompatible: true,
|
|
153
|
+
authoritySchemes: ["environment-reference", "external-vault", "workload-identity"],
|
|
153
154
|
knowledgePageIds: ["provider.railway", "services.credentials", "vault.rotation"]
|
|
154
155
|
}]
|
|
155
156
|
},
|