@treeseed/sdk 0.13.0-rc.49 → 0.13.0-rc.50
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/deployment/schemas.d.ts +972 -30
- package/dist/deployment/schemas.js +21 -0
- package/package.json +1 -1
|
@@ -127,6 +127,25 @@ const packageEndpointSchema = z.object({
|
|
|
127
127
|
if (endpoint.visibility === "host" && !endpoint.healthGate) context.addIssue({ code: z.ZodIssueCode.custom, path: ["healthGate"], message: "Host-visible endpoints require a health gate." });
|
|
128
128
|
if (endpoint.visibility === "private" && endpoint.defaultAlias) context.addIssue({ code: z.ZodIssueCode.custom, path: ["defaultAlias"], message: "Private endpoints cannot declare host aliases." });
|
|
129
129
|
});
|
|
130
|
+
const environmentName = z.string().regex(/^[A-Z][A-Z0-9_]{0,127}$/u, "Environment names must use portable uppercase identifiers.");
|
|
131
|
+
const componentSecretPath = z.string().regex(/^\/etc\/treeseed\/credentials\/[a-z0-9][a-z0-9._-]{0,127}$/u, "Secret inputs must use manager-owned credential paths.");
|
|
132
|
+
const componentConfigurationPath = z.string().regex(/^\/etc\/treeseed\/components\/[a-z][a-z0-9.-]*\/[a-z0-9][a-z0-9._-]{0,127}$/u, "Configuration inputs must use manager-owned component paths.");
|
|
133
|
+
const componentRuntimeConfigurationSchema = z.object({
|
|
134
|
+
environment: z.array(z.object({ name: environmentName, required: z.boolean(), default: z.string().max(16384).optional() }).strict()).default([]),
|
|
135
|
+
secretEnvironment: z.array(z.object({ name: environmentName, required: z.boolean() }).strict()).default([]),
|
|
136
|
+
secretFiles: z.array(z.object({ id: identifier, path: componentSecretPath, required: z.boolean() }).strict()).default([]),
|
|
137
|
+
files: z.array(z.object({ id: identifier, path: componentConfigurationPath, required: z.boolean(), sensitive: z.boolean().default(false) }).strict()).default([])
|
|
138
|
+
}).strict().default({ environment: [], secretEnvironment: [], secretFiles: [], files: [] }).superRefine((configuration, context) => {
|
|
139
|
+
const environment = configuration.environment.map(({ name }) => name);
|
|
140
|
+
const secretEnvironment = configuration.secretEnvironment.map(({ name }) => name);
|
|
141
|
+
for (const [path, values] of [["environment", environment], ["secretEnvironment", secretEnvironment]]) {
|
|
142
|
+
if (new Set(values).size !== values.length) context.addIssue({ code: z.ZodIssueCode.custom, path: [path], message: `Duplicate ${path} inputs are not allowed.` });
|
|
143
|
+
}
|
|
144
|
+
const overlap = environment.filter((name) => secretEnvironment.includes(name));
|
|
145
|
+
if (overlap.length) context.addIssue({ code: z.ZodIssueCode.custom, path: ["secretEnvironment"], message: `Environment inputs cannot have both public and secret custody: ${overlap.join(", ")}.` });
|
|
146
|
+
const filePaths = [...configuration.secretFiles.map(({ path }) => path), ...configuration.files.map(({ path }) => path)];
|
|
147
|
+
if (new Set(filePaths).size !== filePaths.length) context.addIssue({ code: z.ZodIssueCode.custom, path: ["files"], message: "Component file input paths must be unique." });
|
|
148
|
+
});
|
|
130
149
|
const packageRuntimeSchema = z.object({
|
|
131
150
|
schemaVersion: z.literal("treeseed.package-runtime/v1"),
|
|
132
151
|
componentId: identifier,
|
|
@@ -135,6 +154,7 @@ const packageRuntimeSchema = z.object({
|
|
|
135
154
|
projectName: identifier,
|
|
136
155
|
files: z.array(z.object({ path: z.string().min(1), digest }).strict()).min(1)
|
|
137
156
|
}).strict(),
|
|
157
|
+
configuration: componentRuntimeConfigurationSchema,
|
|
138
158
|
services: z.array(z.object({ id: identifier, composeService: identifier, endpoints: z.array(packageEndpointSchema) }).strict()).min(1),
|
|
139
159
|
stateVolumes: z.array(z.object({ id: identifier, volume: z.string().min(1), backup: z.enum(["required", "optional", "none"]) }).strict()),
|
|
140
160
|
migrations: z.array(z.object({ id: identifier, order: z.number().int().nonnegative(), backupRequired: z.boolean() }).strict()),
|
|
@@ -148,6 +168,7 @@ const packageRuntimeSchema = z.object({
|
|
|
148
168
|
}).strict().superRefine((runtime, context) => {
|
|
149
169
|
const endpointIds = runtime.services.flatMap((service) => service.endpoints.map((endpoint) => `${service.id}.${endpoint.id}`));
|
|
150
170
|
if (new Set(endpointIds).size !== endpointIds.length) context.addIssue({ code: z.ZodIssueCode.custom, path: ["services"], message: "Endpoint identities must be unique within a component." });
|
|
171
|
+
for (const file of runtime.configuration.files) if (!file.path.startsWith(`/etc/treeseed/components/${runtime.componentId}/`)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["configuration", "files"], message: `Configuration file ${file.id} is outside component ${runtime.componentId} custody.` });
|
|
151
172
|
});
|
|
152
173
|
const catalogPackageSchema = z.object({ name: z.string().regex(/^treeseed(?:-[a-z0-9-]+)?$/u), version: packageVersion, architecture: z.enum(["amd64", "all"]), origin: z.literal("TreeSeed Deployment"), order: z.number().int().nonnegative() }).strict();
|
|
153
174
|
const catalogImageSchema = z.object({ role: identifier, repository: ociRepository, digest, platforms: z.array(z.enum(["linux/amd64", "linux/arm64"])).min(1), consumers: z.array(identifier).min(1) }).strict();
|