@treeseed/sdk 0.13.0-rc.102 → 0.13.0-rc.103

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-09T05:56:47.945Z"}
1
+ {"completedAt":"2026-09-09T06:37:08.486Z"}
@@ -1,5 +1,6 @@
1
1
  export * from './schemas.js';
2
2
  export * from './postgres/contracts.js';
3
+ export * from './postgres/requirements.js';
3
4
  export * from './canonical.js';
4
5
  export * from './catalog.js';
5
6
  export * from './topology.js';
@@ -1,5 +1,6 @@
1
1
  export * from "./schemas.js";
2
2
  export * from "./postgres/contracts.js";
3
+ export * from "./postgres/requirements.js";
3
4
  export * from "./canonical.js";
4
5
  export * from "./catalog.js";
5
6
  export * from "./topology.js";
@@ -48,7 +48,7 @@ const postgresTopologySchema = z.object({
48
48
  if (!unique(value.servers.map((server) => server.id)) || !unique(value.requirements.map((requirement) => requirement.id)) || !unique(value.allocations.map((allocation) => allocation.requirementId))) fail("Server, requirement and allocation identities must be unique.");
49
49
  if (value.servers.filter((server) => server.mode === "shared").length > 1) fail("An environment has at most one default shared server.");
50
50
  if (value.servers.some((server) => server.installationId !== value.installationId || server.environment !== value.environment)) fail("Servers must belong to this installation and environment.");
51
- const databases = /* @__PURE__ */ new Set(), roles = /* @__PURE__ */ new Set();
51
+ const databases = /* @__PURE__ */ new Set(), roles = /* @__PURE__ */ new Set(), credentials = /* @__PURE__ */ new Set();
52
52
  for (const allocation of value.allocations) {
53
53
  const server = value.servers.find((entry) => entry.id === allocation.serverId);
54
54
  const requirement = value.requirements.find((entry) => entry.id === allocation.requirementId);
@@ -60,6 +60,10 @@ const postgresTopologySchema = z.object({
60
60
  const databaseKey = `${server.id}:${allocation.database}`;
61
61
  if (databases.has(databaseKey)) fail("Applications must not share an allocated database.");
62
62
  databases.add(databaseKey);
63
+ for (const reference of [allocation.migrationCredentialReference, allocation.runtimeCredentialReference]) {
64
+ if (credentials.has(reference)) fail("Applications must not share database credential references.");
65
+ credentials.add(reference);
66
+ }
63
67
  for (const role of [allocation.ownerRole, allocation.migrationRole, allocation.runtimeRole]) {
64
68
  const key = `${server.id}:${role}`;
65
69
  if (roles.has(key)) fail("Applications must not share database roles.");
@@ -0,0 +1,14 @@
1
+ /** Call after artifact authenticity verification, with the complete selected
2
+ * component inventory. Host configuration cannot weaken a package requirement.
3
+ */
4
+ export declare function verifyHostPostgresRequirements(hostInput: unknown, releaseInputs: unknown[]): {
5
+ verified: true;
6
+ requirements: {
7
+ id: string;
8
+ componentId: string;
9
+ enabled: boolean;
10
+ supportedMajors: [number, ...number[]];
11
+ extensions: string[];
12
+ runtimeConnectionLimit: number;
13
+ }[];
14
+ };
@@ -0,0 +1,30 @@
1
+ import { componentReleaseSchema, hostConfigurationSchema } from "../schemas.js";
2
+ import { canonicalDeploymentJson, deploymentDigest } from "../canonical.js";
3
+ function verifyHostPostgresRequirements(hostInput, releaseInputs) {
4
+ const host = hostConfigurationSchema.parse(hostInput);
5
+ const releases = releaseInputs.map((input) => componentReleaseSchema.parse(input));
6
+ if (new Set(releases.map((item) => item.componentId)).size !== releases.length) throw new Error("Duplicate component release inventory");
7
+ if (Object.entries(host.components).some(([id, selection]) => selection.enabled && !releases.some((release) => release.componentId === id))) throw new Error("Selected component release inventory is incomplete");
8
+ const requirements = [];
9
+ for (const release of releases) {
10
+ const selection = host.components[release.componentId];
11
+ if (!selection) continue;
12
+ if (deploymentDigest(release.runtime) !== release.runtimeDigest) throw new Error("Component runtime digest mismatch");
13
+ for (const requirement of release.runtime.postgresRequirements ?? []) requirements.push({
14
+ ...requirement,
15
+ componentId: release.componentId,
16
+ enabled: selection.enabled
17
+ });
18
+ }
19
+ if (new Set(requirements.map((item) => item.id)).size !== requirements.length) throw new Error("Component database requirement identities collide");
20
+ const normalize = (items) => items.map((item) => ({
21
+ ...item,
22
+ supportedMajors: [...item.supportedMajors].sort((a, b) => a - b),
23
+ extensions: [...item.extensions].sort()
24
+ })).sort((a, b) => a.id.localeCompare(b.id));
25
+ if (canonicalDeploymentJson(normalize(requirements)) !== canonicalDeploymentJson(normalize(host.postgres?.requirements ?? []))) throw new Error("Host database requirements differ from selected immutable components");
26
+ return { verified: true, requirements };
27
+ }
28
+ export {
29
+ verifyHostPostgresRequirements
30
+ };
@@ -552,7 +552,7 @@ export declare const hostComponentSchema: z.ZodObject<{
552
552
  };
553
553
  }> | undefined;
554
554
  }>;
555
- export declare const hostConfigurationSchema: z.ZodObject<{
555
+ export declare const hostConfigurationSchema: z.ZodEffects<z.ZodObject<{
556
556
  schemaVersion: z.ZodLiteral<"treeseed.host/v1">;
557
557
  configurationId: z.ZodString;
558
558
  generation: z.ZodNumber;
@@ -908,6 +908,278 @@ export declare const hostConfigurationSchema: z.ZodObject<{
908
908
  };
909
909
  }> | undefined;
910
910
  }>>;
911
+ postgres: z.ZodOptional<z.ZodEffects<z.ZodObject<{
912
+ schemaVersion: z.ZodLiteral<"treeseed.postgres-topology/v1">;
913
+ installationId: z.ZodString;
914
+ environment: z.ZodEnum<["staging", "production"]>;
915
+ servers: z.ZodArray<z.ZodObject<{
916
+ id: z.ZodString;
917
+ installationId: z.ZodString;
918
+ environment: z.ZodEnum<["staging", "production"]>;
919
+ mode: z.ZodEnum<["shared", "dedicated", "external"]>;
920
+ hostname: z.ZodString;
921
+ port: z.ZodNumber;
922
+ major: z.ZodNumber;
923
+ extensions: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">, string[], string[]>;
924
+ tls: z.ZodObject<{
925
+ mode: z.ZodLiteral<"verify-full">;
926
+ trustReference: z.ZodString;
927
+ }, "strict", z.ZodTypeAny, {
928
+ mode: "verify-full";
929
+ trustReference: string;
930
+ }, {
931
+ mode: "verify-full";
932
+ trustReference: string;
933
+ }>;
934
+ }, "strict", z.ZodTypeAny, {
935
+ id: string;
936
+ mode: "shared" | "dedicated" | "external";
937
+ environment: "production" | "staging";
938
+ port: number;
939
+ major: number;
940
+ extensions: string[];
941
+ installationId: string;
942
+ hostname: string;
943
+ tls: {
944
+ mode: "verify-full";
945
+ trustReference: string;
946
+ };
947
+ }, {
948
+ id: string;
949
+ mode: "shared" | "dedicated" | "external";
950
+ environment: "production" | "staging";
951
+ port: number;
952
+ major: number;
953
+ extensions: string[];
954
+ installationId: string;
955
+ hostname: string;
956
+ tls: {
957
+ mode: "verify-full";
958
+ trustReference: string;
959
+ };
960
+ }>, "many">;
961
+ requirements: z.ZodArray<z.ZodObject<{
962
+ id: z.ZodString;
963
+ componentId: z.ZodString;
964
+ enabled: z.ZodBoolean;
965
+ supportedMajors: z.ZodEffects<z.ZodArray<z.ZodNumber, "atleastone">, [number, ...number[]], [number, ...number[]]>;
966
+ extensions: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">, string[], string[]>;
967
+ runtimeConnectionLimit: z.ZodNumber;
968
+ }, "strict", z.ZodTypeAny, {
969
+ id: string;
970
+ componentId: string;
971
+ enabled: boolean;
972
+ supportedMajors: [number, ...number[]];
973
+ extensions: string[];
974
+ runtimeConnectionLimit: number;
975
+ }, {
976
+ id: string;
977
+ componentId: string;
978
+ enabled: boolean;
979
+ supportedMajors: [number, ...number[]];
980
+ extensions: string[];
981
+ runtimeConnectionLimit: number;
982
+ }>, "many">;
983
+ allocations: z.ZodArray<z.ZodEffects<z.ZodObject<{
984
+ requirementId: z.ZodString;
985
+ serverId: z.ZodString;
986
+ database: z.ZodEffects<z.ZodString, string, string>;
987
+ ownerRole: z.ZodEffects<z.ZodString, string, string>;
988
+ migrationRole: z.ZodEffects<z.ZodString, string, string>;
989
+ runtimeRole: z.ZodEffects<z.ZodString, string, string>;
990
+ migrationCredentialReference: z.ZodString;
991
+ runtimeCredentialReference: z.ZodString;
992
+ onDisable: z.ZodLiteral<"preserve">;
993
+ }, "strict", z.ZodTypeAny, {
994
+ requirementId: string;
995
+ serverId: string;
996
+ database: string;
997
+ ownerRole: string;
998
+ migrationRole: string;
999
+ runtimeRole: string;
1000
+ migrationCredentialReference: string;
1001
+ runtimeCredentialReference: string;
1002
+ onDisable: "preserve";
1003
+ }, {
1004
+ requirementId: string;
1005
+ serverId: string;
1006
+ database: string;
1007
+ ownerRole: string;
1008
+ migrationRole: string;
1009
+ runtimeRole: string;
1010
+ migrationCredentialReference: string;
1011
+ runtimeCredentialReference: string;
1012
+ onDisable: "preserve";
1013
+ }>, {
1014
+ requirementId: string;
1015
+ serverId: string;
1016
+ database: string;
1017
+ ownerRole: string;
1018
+ migrationRole: string;
1019
+ runtimeRole: string;
1020
+ migrationCredentialReference: string;
1021
+ runtimeCredentialReference: string;
1022
+ onDisable: "preserve";
1023
+ }, {
1024
+ requirementId: string;
1025
+ serverId: string;
1026
+ database: string;
1027
+ ownerRole: string;
1028
+ migrationRole: string;
1029
+ runtimeRole: string;
1030
+ migrationCredentialReference: string;
1031
+ runtimeCredentialReference: string;
1032
+ onDisable: "preserve";
1033
+ }>, "many">;
1034
+ }, "strict", z.ZodTypeAny, {
1035
+ schemaVersion: "treeseed.postgres-topology/v1";
1036
+ environment: "production" | "staging";
1037
+ installationId: string;
1038
+ servers: {
1039
+ id: string;
1040
+ mode: "shared" | "dedicated" | "external";
1041
+ environment: "production" | "staging";
1042
+ port: number;
1043
+ major: number;
1044
+ extensions: string[];
1045
+ installationId: string;
1046
+ hostname: string;
1047
+ tls: {
1048
+ mode: "verify-full";
1049
+ trustReference: string;
1050
+ };
1051
+ }[];
1052
+ requirements: {
1053
+ id: string;
1054
+ componentId: string;
1055
+ enabled: boolean;
1056
+ supportedMajors: [number, ...number[]];
1057
+ extensions: string[];
1058
+ runtimeConnectionLimit: number;
1059
+ }[];
1060
+ allocations: {
1061
+ requirementId: string;
1062
+ serverId: string;
1063
+ database: string;
1064
+ ownerRole: string;
1065
+ migrationRole: string;
1066
+ runtimeRole: string;
1067
+ migrationCredentialReference: string;
1068
+ runtimeCredentialReference: string;
1069
+ onDisable: "preserve";
1070
+ }[];
1071
+ }, {
1072
+ schemaVersion: "treeseed.postgres-topology/v1";
1073
+ environment: "production" | "staging";
1074
+ installationId: string;
1075
+ servers: {
1076
+ id: string;
1077
+ mode: "shared" | "dedicated" | "external";
1078
+ environment: "production" | "staging";
1079
+ port: number;
1080
+ major: number;
1081
+ extensions: string[];
1082
+ installationId: string;
1083
+ hostname: string;
1084
+ tls: {
1085
+ mode: "verify-full";
1086
+ trustReference: string;
1087
+ };
1088
+ }[];
1089
+ requirements: {
1090
+ id: string;
1091
+ componentId: string;
1092
+ enabled: boolean;
1093
+ supportedMajors: [number, ...number[]];
1094
+ extensions: string[];
1095
+ runtimeConnectionLimit: number;
1096
+ }[];
1097
+ allocations: {
1098
+ requirementId: string;
1099
+ serverId: string;
1100
+ database: string;
1101
+ ownerRole: string;
1102
+ migrationRole: string;
1103
+ runtimeRole: string;
1104
+ migrationCredentialReference: string;
1105
+ runtimeCredentialReference: string;
1106
+ onDisable: "preserve";
1107
+ }[];
1108
+ }>, {
1109
+ schemaVersion: "treeseed.postgres-topology/v1";
1110
+ environment: "production" | "staging";
1111
+ installationId: string;
1112
+ servers: {
1113
+ id: string;
1114
+ mode: "shared" | "dedicated" | "external";
1115
+ environment: "production" | "staging";
1116
+ port: number;
1117
+ major: number;
1118
+ extensions: string[];
1119
+ installationId: string;
1120
+ hostname: string;
1121
+ tls: {
1122
+ mode: "verify-full";
1123
+ trustReference: string;
1124
+ };
1125
+ }[];
1126
+ requirements: {
1127
+ id: string;
1128
+ componentId: string;
1129
+ enabled: boolean;
1130
+ supportedMajors: [number, ...number[]];
1131
+ extensions: string[];
1132
+ runtimeConnectionLimit: number;
1133
+ }[];
1134
+ allocations: {
1135
+ requirementId: string;
1136
+ serverId: string;
1137
+ database: string;
1138
+ ownerRole: string;
1139
+ migrationRole: string;
1140
+ runtimeRole: string;
1141
+ migrationCredentialReference: string;
1142
+ runtimeCredentialReference: string;
1143
+ onDisable: "preserve";
1144
+ }[];
1145
+ }, {
1146
+ schemaVersion: "treeseed.postgres-topology/v1";
1147
+ environment: "production" | "staging";
1148
+ installationId: string;
1149
+ servers: {
1150
+ id: string;
1151
+ mode: "shared" | "dedicated" | "external";
1152
+ environment: "production" | "staging";
1153
+ port: number;
1154
+ major: number;
1155
+ extensions: string[];
1156
+ installationId: string;
1157
+ hostname: string;
1158
+ tls: {
1159
+ mode: "verify-full";
1160
+ trustReference: string;
1161
+ };
1162
+ }[];
1163
+ requirements: {
1164
+ id: string;
1165
+ componentId: string;
1166
+ enabled: boolean;
1167
+ supportedMajors: [number, ...number[]];
1168
+ extensions: string[];
1169
+ runtimeConnectionLimit: number;
1170
+ }[];
1171
+ allocations: {
1172
+ requirementId: string;
1173
+ serverId: string;
1174
+ database: string;
1175
+ ownerRole: string;
1176
+ migrationRole: string;
1177
+ runtimeRole: string;
1178
+ migrationCredentialReference: string;
1179
+ runtimeCredentialReference: string;
1180
+ onDisable: "preserve";
1181
+ }[];
1182
+ }>>;
911
1183
  network: z.ZodObject<{
912
1184
  manager: z.ZodObject<{
913
1185
  binding: z.ZodString;
@@ -1556,6 +1828,400 @@ export declare const hostConfigurationSchema: z.ZodObject<{
1556
1828
  provider: "file" | "systemd-credential";
1557
1829
  reference: string;
1558
1830
  }>;
1831
+ postgres?: {
1832
+ schemaVersion: "treeseed.postgres-topology/v1";
1833
+ environment: "production" | "staging";
1834
+ installationId: string;
1835
+ servers: {
1836
+ id: string;
1837
+ mode: "shared" | "dedicated" | "external";
1838
+ environment: "production" | "staging";
1839
+ port: number;
1840
+ major: number;
1841
+ extensions: string[];
1842
+ installationId: string;
1843
+ hostname: string;
1844
+ tls: {
1845
+ mode: "verify-full";
1846
+ trustReference: string;
1847
+ };
1848
+ }[];
1849
+ requirements: {
1850
+ id: string;
1851
+ componentId: string;
1852
+ enabled: boolean;
1853
+ supportedMajors: [number, ...number[]];
1854
+ extensions: string[];
1855
+ runtimeConnectionLimit: number;
1856
+ }[];
1857
+ allocations: {
1858
+ requirementId: string;
1859
+ serverId: string;
1860
+ database: string;
1861
+ ownerRole: string;
1862
+ migrationRole: string;
1863
+ runtimeRole: string;
1864
+ migrationCredentialReference: string;
1865
+ runtimeCredentialReference: string;
1866
+ onDisable: "preserve";
1867
+ }[];
1868
+ } | undefined;
1869
+ security?: {
1870
+ sandbox: {
1871
+ runtime: "kata-runtime-rs-qemu";
1872
+ profiles: {
1873
+ id: string;
1874
+ guestImage: string;
1875
+ guestImageDigest: string;
1876
+ }[];
1877
+ required: boolean;
1878
+ brokerSocket: string;
1879
+ modelGateway: {
1880
+ provider: "openai";
1881
+ upstreamBaseUrl: "https://api.openai.com";
1882
+ allowedModels: string[];
1883
+ };
1884
+ };
1885
+ providerVolume: {
1886
+ encryption: "luks2";
1887
+ backingPath: string;
1888
+ mountPath: string;
1889
+ sizeBytes: number;
1890
+ unlock: "systemd-credential" | "tpm2";
1891
+ recoveryRequired: true;
1892
+ };
1893
+ applicationEncryption: {
1894
+ provider: "systemd-credential";
1895
+ activeKeyVersion: number;
1896
+ diagnosticsKeyVersion: number;
1897
+ };
1898
+ } | undefined;
1899
+ }, {
1900
+ schemaVersion: "treeseed.host/v1";
1901
+ runtime: {
1902
+ management: "external" | "managed";
1903
+ environment?: "development" | "production" | undefined;
1904
+ dataRoot?: string | undefined;
1905
+ };
1906
+ components: Record<string, {
1907
+ enabled: boolean;
1908
+ track: "development" | "stable";
1909
+ resources?: {
1910
+ cpuCores?: number | undefined;
1911
+ memoryBytes?: number | undefined;
1912
+ storageBytes?: number | undefined;
1913
+ gpuDevices?: string[] | undefined;
1914
+ } | undefined;
1915
+ profile?: string | undefined;
1916
+ aliases?: Record<string, string> | undefined;
1917
+ configuration?: Record<string, unknown> | undefined;
1918
+ connections?: Record<string, {
1919
+ kind: "local";
1920
+ componentId: string;
1921
+ serviceId: string;
1922
+ endpointId: string;
1923
+ } | {
1924
+ kind: "remote";
1925
+ audience: string;
1926
+ url: string;
1927
+ authentication: {
1928
+ mode: "none" | "application" | "mtls" | "bearer";
1929
+ secretRef?: string | undefined;
1930
+ };
1931
+ tls: {
1932
+ trust: "secret" | "system" | "spki";
1933
+ serverName?: string | undefined;
1934
+ caSecretRef?: string | undefined;
1935
+ spkiSha256?: string | undefined;
1936
+ };
1937
+ healthGate: {
1938
+ timeoutSeconds: number;
1939
+ protocol: "http" | "tcp" | "https";
1940
+ path?: string | undefined;
1941
+ };
1942
+ }> | undefined;
1943
+ }>;
1944
+ network: {
1945
+ manager: {
1946
+ binding: string;
1947
+ aliases?: string[] | undefined;
1948
+ sans?: string[] | undefined;
1949
+ trustedLanCidrs?: string[] | undefined;
1950
+ };
1951
+ };
1952
+ host: {
1953
+ id: string;
1954
+ role: string;
1955
+ architecture: "amd64";
1956
+ };
1957
+ generation: number;
1958
+ configurationId: string;
1959
+ updates: {
1960
+ development: {
1961
+ pollSeconds: 60;
1962
+ };
1963
+ stable: {
1964
+ metadataPollSeconds: number;
1965
+ maintenanceWindow: {
1966
+ weekday: "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday";
1967
+ localTime: string;
1968
+ jitterMinutes: number;
1969
+ };
1970
+ };
1971
+ defaultTrack: "development" | "stable";
1972
+ };
1973
+ fleet: {
1974
+ rolloutGroup: string;
1975
+ receiptReporting: {
1976
+ enabled: boolean;
1977
+ intervalSeconds: number;
1978
+ connection?: {
1979
+ kind: "local";
1980
+ componentId: string;
1981
+ serviceId: string;
1982
+ endpointId: string;
1983
+ } | {
1984
+ kind: "remote";
1985
+ audience: string;
1986
+ url: string;
1987
+ authentication: {
1988
+ mode: "none" | "application" | "mtls" | "bearer";
1989
+ secretRef?: string | undefined;
1990
+ };
1991
+ tls: {
1992
+ trust: "secret" | "system" | "spki";
1993
+ serverName?: string | undefined;
1994
+ caSecretRef?: string | undefined;
1995
+ spkiSha256?: string | undefined;
1996
+ };
1997
+ healthGate: {
1998
+ timeoutSeconds: number;
1999
+ protocol: "http" | "tcp" | "https";
2000
+ path?: string | undefined;
2001
+ };
2002
+ } | undefined;
2003
+ };
2004
+ };
2005
+ secrets: Record<string, {
2006
+ provider: "file" | "systemd-credential";
2007
+ reference: string;
2008
+ }>;
2009
+ postgres?: {
2010
+ schemaVersion: "treeseed.postgres-topology/v1";
2011
+ environment: "production" | "staging";
2012
+ installationId: string;
2013
+ servers: {
2014
+ id: string;
2015
+ mode: "shared" | "dedicated" | "external";
2016
+ environment: "production" | "staging";
2017
+ port: number;
2018
+ major: number;
2019
+ extensions: string[];
2020
+ installationId: string;
2021
+ hostname: string;
2022
+ tls: {
2023
+ mode: "verify-full";
2024
+ trustReference: string;
2025
+ };
2026
+ }[];
2027
+ requirements: {
2028
+ id: string;
2029
+ componentId: string;
2030
+ enabled: boolean;
2031
+ supportedMajors: [number, ...number[]];
2032
+ extensions: string[];
2033
+ runtimeConnectionLimit: number;
2034
+ }[];
2035
+ allocations: {
2036
+ requirementId: string;
2037
+ serverId: string;
2038
+ database: string;
2039
+ ownerRole: string;
2040
+ migrationRole: string;
2041
+ runtimeRole: string;
2042
+ migrationCredentialReference: string;
2043
+ runtimeCredentialReference: string;
2044
+ onDisable: "preserve";
2045
+ }[];
2046
+ } | undefined;
2047
+ security?: {
2048
+ sandbox: {
2049
+ runtime: "kata-runtime-rs-qemu";
2050
+ profiles: {
2051
+ id: string;
2052
+ guestImage: string;
2053
+ guestImageDigest: string;
2054
+ }[];
2055
+ required: boolean;
2056
+ brokerSocket: string;
2057
+ modelGateway: {
2058
+ provider: "openai";
2059
+ upstreamBaseUrl: "https://api.openai.com";
2060
+ allowedModels: string[];
2061
+ };
2062
+ };
2063
+ providerVolume: {
2064
+ encryption: "luks2";
2065
+ backingPath: string;
2066
+ mountPath: string;
2067
+ sizeBytes: number;
2068
+ unlock: "systemd-credential" | "tpm2";
2069
+ recoveryRequired: true;
2070
+ };
2071
+ applicationEncryption: {
2072
+ provider: "systemd-credential";
2073
+ activeKeyVersion: number;
2074
+ diagnosticsKeyVersion: number;
2075
+ };
2076
+ } | undefined;
2077
+ }>, {
2078
+ schemaVersion: "treeseed.host/v1";
2079
+ runtime: {
2080
+ environment: "development" | "production";
2081
+ management: "external" | "managed";
2082
+ dataRoot?: string | undefined;
2083
+ };
2084
+ components: Record<string, {
2085
+ resources: {
2086
+ gpuDevices: string[];
2087
+ cpuCores?: number | undefined;
2088
+ memoryBytes?: number | undefined;
2089
+ storageBytes?: number | undefined;
2090
+ };
2091
+ enabled: boolean;
2092
+ track: "development" | "stable";
2093
+ aliases: Record<string, string>;
2094
+ configuration: Record<string, unknown>;
2095
+ connections: Record<string, {
2096
+ kind: "local";
2097
+ componentId: string;
2098
+ serviceId: string;
2099
+ endpointId: string;
2100
+ } | {
2101
+ kind: "remote";
2102
+ audience: string;
2103
+ url: string;
2104
+ authentication: {
2105
+ mode: "none" | "application" | "mtls" | "bearer";
2106
+ secretRef?: string | undefined;
2107
+ };
2108
+ tls: {
2109
+ trust: "secret" | "system" | "spki";
2110
+ serverName?: string | undefined;
2111
+ caSecretRef?: string | undefined;
2112
+ spkiSha256?: string | undefined;
2113
+ };
2114
+ healthGate: {
2115
+ timeoutSeconds: number;
2116
+ protocol: "http" | "tcp" | "https";
2117
+ path?: string | undefined;
2118
+ };
2119
+ }>;
2120
+ profile?: string | undefined;
2121
+ }>;
2122
+ network: {
2123
+ manager: {
2124
+ aliases: string[];
2125
+ binding: string;
2126
+ sans: string[];
2127
+ trustedLanCidrs: string[];
2128
+ };
2129
+ };
2130
+ host: {
2131
+ id: string;
2132
+ role: string;
2133
+ architecture: "amd64";
2134
+ };
2135
+ generation: number;
2136
+ configurationId: string;
2137
+ updates: {
2138
+ development: {
2139
+ pollSeconds: 60;
2140
+ };
2141
+ stable: {
2142
+ metadataPollSeconds: number;
2143
+ maintenanceWindow: {
2144
+ weekday: "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday";
2145
+ localTime: string;
2146
+ jitterMinutes: number;
2147
+ };
2148
+ };
2149
+ defaultTrack: "development" | "stable";
2150
+ };
2151
+ fleet: {
2152
+ rolloutGroup: string;
2153
+ receiptReporting: {
2154
+ enabled: boolean;
2155
+ intervalSeconds: number;
2156
+ connection?: {
2157
+ kind: "local";
2158
+ componentId: string;
2159
+ serviceId: string;
2160
+ endpointId: string;
2161
+ } | {
2162
+ kind: "remote";
2163
+ audience: string;
2164
+ url: string;
2165
+ authentication: {
2166
+ mode: "none" | "application" | "mtls" | "bearer";
2167
+ secretRef?: string | undefined;
2168
+ };
2169
+ tls: {
2170
+ trust: "secret" | "system" | "spki";
2171
+ serverName?: string | undefined;
2172
+ caSecretRef?: string | undefined;
2173
+ spkiSha256?: string | undefined;
2174
+ };
2175
+ healthGate: {
2176
+ timeoutSeconds: number;
2177
+ protocol: "http" | "tcp" | "https";
2178
+ path?: string | undefined;
2179
+ };
2180
+ } | undefined;
2181
+ };
2182
+ };
2183
+ secrets: Record<string, {
2184
+ provider: "file" | "systemd-credential";
2185
+ reference: string;
2186
+ }>;
2187
+ postgres?: {
2188
+ schemaVersion: "treeseed.postgres-topology/v1";
2189
+ environment: "production" | "staging";
2190
+ installationId: string;
2191
+ servers: {
2192
+ id: string;
2193
+ mode: "shared" | "dedicated" | "external";
2194
+ environment: "production" | "staging";
2195
+ port: number;
2196
+ major: number;
2197
+ extensions: string[];
2198
+ installationId: string;
2199
+ hostname: string;
2200
+ tls: {
2201
+ mode: "verify-full";
2202
+ trustReference: string;
2203
+ };
2204
+ }[];
2205
+ requirements: {
2206
+ id: string;
2207
+ componentId: string;
2208
+ enabled: boolean;
2209
+ supportedMajors: [number, ...number[]];
2210
+ extensions: string[];
2211
+ runtimeConnectionLimit: number;
2212
+ }[];
2213
+ allocations: {
2214
+ requirementId: string;
2215
+ serverId: string;
2216
+ database: string;
2217
+ ownerRole: string;
2218
+ migrationRole: string;
2219
+ runtimeRole: string;
2220
+ migrationCredentialReference: string;
2221
+ runtimeCredentialReference: string;
2222
+ onDisable: "preserve";
2223
+ }[];
2224
+ } | undefined;
1559
2225
  security?: {
1560
2226
  sandbox: {
1561
2227
  runtime: "kata-runtime-rs-qemu";
@@ -1696,6 +2362,44 @@ export declare const hostConfigurationSchema: z.ZodObject<{
1696
2362
  provider: "file" | "systemd-credential";
1697
2363
  reference: string;
1698
2364
  }>;
2365
+ postgres?: {
2366
+ schemaVersion: "treeseed.postgres-topology/v1";
2367
+ environment: "production" | "staging";
2368
+ installationId: string;
2369
+ servers: {
2370
+ id: string;
2371
+ mode: "shared" | "dedicated" | "external";
2372
+ environment: "production" | "staging";
2373
+ port: number;
2374
+ major: number;
2375
+ extensions: string[];
2376
+ installationId: string;
2377
+ hostname: string;
2378
+ tls: {
2379
+ mode: "verify-full";
2380
+ trustReference: string;
2381
+ };
2382
+ }[];
2383
+ requirements: {
2384
+ id: string;
2385
+ componentId: string;
2386
+ enabled: boolean;
2387
+ supportedMajors: [number, ...number[]];
2388
+ extensions: string[];
2389
+ runtimeConnectionLimit: number;
2390
+ }[];
2391
+ allocations: {
2392
+ requirementId: string;
2393
+ serverId: string;
2394
+ database: string;
2395
+ ownerRole: string;
2396
+ migrationRole: string;
2397
+ runtimeRole: string;
2398
+ migrationCredentialReference: string;
2399
+ runtimeCredentialReference: string;
2400
+ onDisable: "preserve";
2401
+ }[];
2402
+ } | undefined;
1699
2403
  security?: {
1700
2404
  sandbox: {
1701
2405
  runtime: "kata-runtime-rs-qemu";
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { AI_MODE_INTERNAL_PATH } from "./ai-mode.js";
3
- import { postgresComponentRequirementSchema } from "./postgres/contracts.js";
3
+ import { postgresComponentRequirementSchema, postgresTopologySchema } from "./postgres/contracts.js";
4
4
  const identifier = z.string().regex(/^[a-z][a-z0-9.-]{1,63}$/u);
5
5
  const digest = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
6
6
  const gitCommit = z.string().regex(/^[a-f0-9]{40}$/u);
@@ -121,6 +121,7 @@ const hostConfigurationSchema = z.object({
121
121
  development: z.object({ pollSeconds: z.literal(60) }).strict()
122
122
  }).strict(),
123
123
  components: z.record(identifier, hostComponentSchema),
124
+ postgres: postgresTopologySchema.optional(),
124
125
  network: z.object({
125
126
  manager: z.object({ binding, aliases: z.array(localAlias).default([]), sans: z.array(z.string().min(1)).default([]), trustedLanCidrs: z.array(z.string().min(1)).default([]) }).strict()
126
127
  }).strict(),
@@ -149,7 +150,21 @@ const hostConfigurationSchema = z.object({
149
150
  providerVolume: z.object({ encryption: z.literal("luks2"), backingPath: z.string().startsWith("/"), mountPath: z.string().startsWith("/"), sizeBytes: z.number().int().min(1073741824), unlock: z.enum(["tpm2", "systemd-credential"]), recoveryRequired: z.literal(true) }).strict(),
150
151
  applicationEncryption: z.object({ provider: z.literal("systemd-credential"), activeKeyVersion: z.number().int().positive(), diagnosticsKeyVersion: z.number().int().positive() }).strict()
151
152
  }).strict().optional()
152
- }).strict();
153
+ }).strict().superRefine((host, context) => {
154
+ if (!host.postgres) return;
155
+ const fail = (message) => context.addIssue({ code: z.ZodIssueCode.custom, path: ["postgres"], message });
156
+ for (const requirement of host.postgres.requirements) {
157
+ if (!host.components[requirement.componentId] || host.components[requirement.componentId].enabled !== requirement.enabled) fail("Database requirements must match configured component activation.");
158
+ }
159
+ for (const allocation of host.postgres.allocations) {
160
+ if (!host.postgres.requirements.find((item) => item.id === allocation.requirementId)?.enabled) continue;
161
+ for (const reference of [allocation.migrationCredentialReference, allocation.runtimeCredentialReference]) {
162
+ if (host.secrets[reference]?.provider !== "systemd-credential" || host.secrets[reference]?.reference !== `/etc/treeseed/credentials/${reference}.cred`) fail("Database credentials require explicit fixed OS custody bindings.");
163
+ }
164
+ const server = host.postgres.servers.find((item) => item.id === allocation.serverId);
165
+ if (server.mode !== "external" && !host.components.postgres?.enabled) fail("Managed database allocations require the PostgreSQL component.");
166
+ }
167
+ });
153
168
  const packageEndpointSchema = z.object({
154
169
  id: identifier,
155
170
  protocol: z.enum(["http", "https", "tcp"]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.13.0-rc.102",
3
+ "version": "0.13.0-rc.103",
4
4
  "description": "Portable TreeSeed contracts, standards, and typed remote control-plane clients.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {