@forgezero/agent 0.1.65 → 0.1.68

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.
@@ -699,7 +699,30 @@ var BUN_RELEASE_SHA256 = "951ee2aee855f08595aeec6225226a298d3fea83a3dcd6465c09cb
699
699
  var ARANGO_SHA256 = "b5a9197b4343f2ed554e1ebc1ef8e6529c7c39cde0035cdc311a4747a3355066";
700
700
  var CLOUDFLARED_SHA256 = "9d71c677db00134c1bd4144b7783486b654ad281b1ea62b4972098d19f770f17";
701
701
  var OS_CATALOG = [
702
- { id: "ubuntu", version: "26.04", architecture: "x64", status: "active" }
702
+ {
703
+ id: "ubuntu",
704
+ version: "26.04",
705
+ architecture: "x64",
706
+ status: "active",
707
+ imageKey: "ubuntu-resolute-20260731",
708
+ imageLabel: "Ubuntu 26.04 LTS Resolute",
709
+ imageVersion: "2026-07-31",
710
+ imageUrl: "https://cloud-images.ubuntu.com/releases/resolute/release-20260731/ubuntu-26.04-server-cloudimg-amd64.img",
711
+ imageSha256: "9dc7c5363c0146a08ba0c9aa834d82c2c6dfbb1c471ad9a2f0aba1189e21be05",
712
+ confidentialModes: ["sev-snp"]
713
+ },
714
+ {
715
+ id: "ubuntu",
716
+ version: "24.04",
717
+ architecture: "x64",
718
+ status: "active",
719
+ imageKey: "ubuntu-noble-20260705",
720
+ imageLabel: "Ubuntu 24.04 LTS Noble",
721
+ imageVersion: "2026-07-05",
722
+ imageUrl: "https://cloud-images.ubuntu.com/releases/noble/release-20260705/ubuntu-24.04-server-cloudimg-amd64.img",
723
+ imageSha256: "ffe6203da54deeb6db5d2a98a83f9ec8e55f149d3f7ba622e1abe5fa966ee3d6",
724
+ confidentialModes: []
725
+ }
703
726
  ];
704
727
  var SOFTWARE_CATALOG = [
705
728
  { id: "bun", version: "1.3.14", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
@@ -710,7 +733,12 @@ var SOFTWARE_CATALOG = [
710
733
  { id: "cloudflare-warp", version: "2026.6.822.0-min", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
711
734
  { id: "ufw", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
712
735
  { id: "openssh-client", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
713
- { id: "git", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
736
+ { id: "git", version: "ubuntu-26.04", status: "active", os: "ubuntu", osVersion: "26.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
737
+ { id: "docker", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
738
+ { id: "nginx", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
739
+ { id: "ufw", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
740
+ { id: "openssh-client", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" },
741
+ { id: "git", version: "ubuntu-24.04", status: "active", os: "ubuntu", osVersion: "24.04", architecture: "x64", evidence: "reviewed-strategy-and-tests" }
714
742
  ];
715
743
  var UBUNTU_2604_X64 = [
716
744
  { requirement: { id: "bun", version: "1.3.14" } },
@@ -723,6 +751,15 @@ var UBUNTU_2604_X64 = [
723
751
  { requirement: { id: "openssh-client", version: "ubuntu-26.04" } },
724
752
  { requirement: { id: "git", version: "ubuntu-26.04" } }
725
753
  ];
754
+ var UBUNTU_2404_X64 = [
755
+ { requirement: { id: "bun", version: "1.3.14" } },
756
+ { requirement: { id: "docker", version: "ubuntu-24.04" } },
757
+ { requirement: { id: "nginx", version: "ubuntu-24.04" } },
758
+ { requirement: { id: "ufw", version: "ubuntu-24.04" } },
759
+ { requirement: { id: "openssh-client", version: "ubuntu-24.04" } },
760
+ { requirement: { id: "git", version: "ubuntu-24.04" } }
761
+ ];
762
+ var strategiesFor = (observation) => observation.os.id === "ubuntu" && observation.architecture === "x64" ? observation.os.versionId === "26.04" ? UBUNTU_2604_X64 : observation.os.versionId === "24.04" ? UBUNTU_2404_X64 : undefined : undefined;
726
763
  var path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
727
764
  var DOCKER_DAEMON_PATH = "/etc/docker/daemon.json";
728
765
  var DOCKER_DAEMON_CONFIG = `${JSON.stringify({
@@ -769,7 +806,7 @@ var aptInstall = async (name) => {
769
806
  };
770
807
  async function executeSoftwareOperation(operation) {
771
808
  const { software, version } = operation;
772
- if (!UBUNTU_2604_X64.some(({ requirement }) => requirement.id === software && requirement.version === version)) {
809
+ if (![...UBUNTU_2604_X64, ...UBUNTU_2404_X64].some(({ requirement }) => requirement.id === software && requirement.version === version)) {
773
810
  return { exitCode: 2, output: "unsupported software operation" };
774
811
  }
775
812
  if (operation.kind === "check") {
@@ -939,7 +976,7 @@ async function ensureSoftwareRequirements(requirementsInput, options) {
939
976
  }
940
977
  const results = [];
941
978
  for (const requirement of requirements) {
942
- const strategy = UBUNTU_2604_X64.find(({ requirement: candidate }) => candidate.id === requirement.id && candidate.version === requirement.version);
979
+ const strategy = strategiesFor(observation)?.find(({ requirement: candidate }) => candidate.id === requirement.id && candidate.version === requirement.version);
943
980
  if (!strategy)
944
981
  throw new Error(`unsupported software requirement: ${requirement.id}@${requirement.version}`);
945
982
  const before = await options.exec({ kind: "check", software: requirement.id, version: requirement.version });
@@ -2088,7 +2125,7 @@ function requestSoftware(requirements, socketPath = DEFAULT_SOFTWARE_HELPER_SOCK
2088
2125
  }
2089
2126
 
2090
2127
  // src/version.ts
2091
- var VERSION3 = "0.1.65";
2128
+ var VERSION3 = "0.1.68";
2092
2129
 
2093
2130
  // src/egress-policy.ts
2094
2131
  import { realpathSync as realpathSync3 } from "node:fs";
@@ -3075,6 +3112,146 @@ function planProvision(options) {
3075
3112
  };
3076
3113
  }
3077
3114
 
3115
+ // src/ubuntu.ts
3116
+ var current = OS_CATALOG[0];
3117
+ var SUPPORTED_GUEST_IMAGE = Object.freeze({
3118
+ key: current.imageKey,
3119
+ family: `${current.id}-${current.version}`,
3120
+ version: current.imageVersion,
3121
+ label: current.imageLabel,
3122
+ url: current.imageUrl,
3123
+ sha256: current.imageSha256
3124
+ });
3125
+ var SUPPORTED_GUEST_IMAGES = Object.freeze(OS_CATALOG.filter(({ status }) => status === "active").map(({ id, imageKey, imageLabel, imageVersion, version, confidentialModes }) => ({
3126
+ key: imageKey,
3127
+ label: imageLabel,
3128
+ family: `${id}-${version}`,
3129
+ version: imageVersion,
3130
+ confidential: confidentialModes.some((mode) => mode === "sev-snp")
3131
+ })));
3132
+ function supportedGuestImage(imageKey) {
3133
+ return SUPPORTED_GUEST_IMAGES.find(({ key }) => key === imageKey);
3134
+ }
3135
+ function assertSupportedGuestImage(imageKey, confidential = false) {
3136
+ const selected = OS_CATALOG.find((entry) => entry.status === "active" && entry.imageKey === imageKey);
3137
+ if (!selected) {
3138
+ throw new Error(`unsupported guest image ${imageKey}; supported images: ${SUPPORTED_GUEST_IMAGES.map(({ key }) => key).join(", ")}`);
3139
+ }
3140
+ if (confidential && !selected.confidentialModes.some((mode) => mode === "sev-snp")) {
3141
+ throw new Error(`guest image ${imageKey} is not approved for SEV-SNP`);
3142
+ }
3143
+ }
3144
+
3145
+ // src/platform-genesis.ts
3146
+ var SAFE_NAME = /^[a-z][a-z0-9-]{0,62}$/;
3147
+ var SAFE_POOL = /^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$/;
3148
+ var PRIVATE_V4 = /^(?:10\.(?:\d{1,3}\.){2}\d{1,3}|192\.168\.(?:\d{1,3})\.(?:\d{1,3})|172\.(?:1[6-9]|2\d|3[01])\.(?:\d{1,3})\.(?:\d{1,3}))$/;
3149
+ var integer = (value, minimum, maximum, label) => {
3150
+ if (!Number.isInteger(value) || value < minimum || value > maximum) {
3151
+ throw new Error(`platform genesis ${label} is outside the supported range`);
3152
+ }
3153
+ return value;
3154
+ };
3155
+ function validatePlatformGenesisGuests(guests, expectedCount = 3) {
3156
+ if (!Array.isArray(guests) || guests.length !== expectedCount) {
3157
+ throw new Error(`platform genesis requires exactly ${expectedCount} reviewed guest requests`);
3158
+ }
3159
+ const names = new Set;
3160
+ const addresses = new Set;
3161
+ const pools = new Set;
3162
+ return guests.map((input) => {
3163
+ if (!input || typeof input !== "object" || !SAFE_NAME.test(input.name)) {
3164
+ throw new Error("platform genesis guest name is malformed");
3165
+ }
3166
+ if (!PRIVATE_V4.test(input.address))
3167
+ throw new Error("platform genesis guest address must be private IPv4");
3168
+ if (typeof input.confidential !== "boolean")
3169
+ throw new Error("platform genesis confidential requirement is missing");
3170
+ assertSupportedGuestImage(input.imageKey, input.confidential);
3171
+ if (input.cpuPoolKey !== undefined && !SAFE_POOL.test(input.cpuPoolKey)) {
3172
+ throw new Error("platform genesis CPU pool key is malformed");
3173
+ }
3174
+ if (names.has(input.name) || addresses.has(input.address) || input.cpuPoolKey !== undefined && pools.has(input.cpuPoolKey)) {
3175
+ throw new Error("platform genesis guest names, addresses and explicit CPU pools must be unique");
3176
+ }
3177
+ names.add(input.name);
3178
+ addresses.add(input.address);
3179
+ if (input.cpuPoolKey !== undefined)
3180
+ pools.add(input.cpuPoolKey);
3181
+ const physicalCores = integer(input.physicalCores, 1, 256, "physical core count");
3182
+ const vcpu = integer(input.vcpu, 1, 512, "vCPU count");
3183
+ if (vcpu < physicalCores)
3184
+ throw new Error("platform genesis vCPU count cannot be smaller than physical cores");
3185
+ const memoryGib = integer(input.memoryGib, 1, 8192, "memory");
3186
+ const diskGib = integer(input.diskGib, 8, 65536, "disk");
3187
+ const egressGuaranteedMbps = integer(input.egressGuaranteedMbps, 0, 1e6, "guaranteed egress");
3188
+ const egressBurstMbps = integer(input.egressBurstMbps, egressGuaranteedMbps, 1e6, "burst egress");
3189
+ return {
3190
+ name: input.name,
3191
+ address: input.address,
3192
+ imageKey: input.imageKey,
3193
+ ...input.cpuPoolKey ? { cpuPoolKey: input.cpuPoolKey } : {},
3194
+ physicalCores,
3195
+ vcpu,
3196
+ memoryGib,
3197
+ diskGib,
3198
+ egressGuaranteedMbps,
3199
+ egressBurstMbps,
3200
+ confidential: input.confidential
3201
+ };
3202
+ });
3203
+ }
3204
+ var publicKey = (value) => {
3205
+ const normalized = value.trim();
3206
+ if (!/^ssh-(?:ed25519|rsa) [A-Za-z0-9+/]+={0,3}(?: [^\r\n]+)?$/.test(normalized)) {
3207
+ throw new Error("platform genesis SSH public key is malformed");
3208
+ }
3209
+ return normalized;
3210
+ };
3211
+ var claimFor = (guest, keys, action) => {
3212
+ const common = {
3213
+ computeKey: `platform:${guest.name}`,
3214
+ claimToken: "offline-platform-genesis",
3215
+ claimExpiresAtTs: Number.MAX_SAFE_INTEGER,
3216
+ attempt: 1,
3217
+ bootstrap: { kind: "platform-genesis" },
3218
+ spec: {
3219
+ reference: `platform:${guest.name}`,
3220
+ imageKey: guest.imageKey,
3221
+ guestName: guest.name,
3222
+ guestAddress: guest.address,
3223
+ ...guest.cpuPoolKey ? { cpuPoolKey: guest.cpuPoolKey } : {},
3224
+ physicalCores: guest.physicalCores,
3225
+ vcpu: guest.vcpu,
3226
+ memoryGib: guest.memoryGib,
3227
+ diskGib: guest.diskGib,
3228
+ egressGuaranteedMbps: guest.egressGuaranteedMbps,
3229
+ egressBurstMbps: guest.egressBurstMbps,
3230
+ confidential: guest.confidential
3231
+ }
3232
+ };
3233
+ if (action === "delete")
3234
+ return { ...common, action: "delete" };
3235
+ return { ...common, action: "create", access: { sshUser: "forgezero", sshPublicKeys: [...keys] } };
3236
+ };
3237
+ function platformGenesisClaims(guests, sshPublicKeys) {
3238
+ const reviewed = validatePlatformGenesisGuests(guests);
3239
+ const keys = [...new Set(sshPublicKeys.map(publicKey))];
3240
+ if (keys.length === 0)
3241
+ throw new Error("platform genesis requires at least one operator SSH public key");
3242
+ return reviewed.map((guest) => claimFor(guest, keys, "create"));
3243
+ }
3244
+ function platformCommunityRehearsalClaims(seedGuests, rehearsalGuest, sshPublicKeys) {
3245
+ const reviewed = validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4);
3246
+ const keys = [...new Set(sshPublicKeys.map(publicKey))];
3247
+ if (keys.length === 0)
3248
+ throw new Error("platform genesis requires at least one operator SSH public key");
3249
+ return reviewed.map((guest) => claimFor(guest, keys, "create"));
3250
+ }
3251
+ function platformCommunityRehearsalDeletionClaims(seedGuests, rehearsalGuest) {
3252
+ return validatePlatformGenesisGuests([...seedGuests, rehearsalGuest], 4).map((guest) => claimFor(guest, [], "delete"));
3253
+ }
3254
+
3078
3255
  // src/platform-bootstrap-runtime.ts
3079
3256
  import {
3080
3257
  chmodSync as chmodSync5,
@@ -3123,6 +3300,50 @@ var httpsOrigin = (name, raw) => {
3123
3300
  }
3124
3301
  return value.origin;
3125
3302
  };
3303
+ function validatePlatformInitialInventory(value) {
3304
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => !["metalHostname", "region", "computes"].includes(key)) || !/^[A-Za-z0-9][A-Za-z0-9.-]{1,252}$/.test(value.metalHostname) || !value.region || typeof value.region !== "object" || Array.isArray(value.region) || Object.keys(value.region).some((key) => !["key", "label", "country", "city", "confidentialCapable"].includes(key)) || !/^[a-z0-9][a-z0-9-]{0,62}$/.test(value.region.key) || !/^[A-Z]{2}$/.test(value.region.country) || value.region.confidentialCapable !== true || !Array.isArray(value.computes)) {
3305
+ throw new Error("initial platform inventory coordinates are invalid");
3306
+ }
3307
+ safeAtom("initialInventory.region.label", value.region.label);
3308
+ if (value.region.city !== undefined)
3309
+ safeAtom("initialInventory.region.city", value.region.city);
3310
+ const computes = validatePlatformGenesisGuests(value.computes.map((compute) => {
3311
+ if (!compute || typeof compute !== "object" || Array.isArray(compute) || Object.keys(compute).some((key) => ![
3312
+ "name",
3313
+ "address",
3314
+ "imageKey",
3315
+ "cpuPoolKey",
3316
+ "physicalCores",
3317
+ "vcpu",
3318
+ "memoryGib",
3319
+ "diskGib",
3320
+ "egressGuaranteedMbps",
3321
+ "egressBurstMbps",
3322
+ "confidential",
3323
+ "databaseRole",
3324
+ "databaseAgency"
3325
+ ].includes(key)))
3326
+ throw new Error("initial platform compute contains unknown fields");
3327
+ return compute;
3328
+ }));
3329
+ for (let index = 0;index < computes.length; index += 1) {
3330
+ const declared = value.computes[index];
3331
+ const expectedRole = index === 0 ? "master" : "joiner";
3332
+ if (declared.databaseRole !== expectedRole || declared.databaseAgency !== "member" || declared.confidential !== true) {
3333
+ throw new Error("initial platform inventory requires one master, two joiners, three Agency members and confidential compute");
3334
+ }
3335
+ }
3336
+ return {
3337
+ metalHostname: value.metalHostname,
3338
+ region: { ...value.region },
3339
+ computes: value.computes.map((compute, index) => ({
3340
+ ...computes[index],
3341
+ databaseRole: compute.databaseRole,
3342
+ databaseAgency: compute.databaseAgency,
3343
+ confidential: true
3344
+ }))
3345
+ };
3346
+ }
3126
3347
  var systemdValue = (name, raw) => {
3127
3348
  if (/[\0\r\n]/.test(raw))
3128
3349
  throw new Error(`${name} must be single-line.`);
@@ -3208,12 +3429,14 @@ function validatePlatformSharedEnvironment(input) {
3208
3429
  throw new Error("realtime.producer is invalid.");
3209
3430
  }
3210
3431
  }
3432
+ const initialInventory = input.initialInventory ? validatePlatformInitialInventory(input.initialInventory) : undefined;
3211
3433
  return {
3212
3434
  ...input,
3213
3435
  databaseCoordinators: coordinators,
3214
3436
  appOrigin: httpsOrigin("appOrigin", input.appOrigin),
3215
3437
  apiOrigin: httpsOrigin("apiOrigin", input.apiOrigin),
3216
- agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint)
3438
+ agentOtlpEndpoint: httpsOrigin("agentOtlpEndpoint", input.agentOtlpEndpoint),
3439
+ ...initialInventory ? { initialInventory } : {}
3217
3440
  };
3218
3441
  }
3219
3442
  function renderPlatformSharedEnvironment(input) {
@@ -3276,7 +3499,8 @@ function renderPlatformSharedEnvironment(input) {
3276
3499
  FZ_CF_TUNNEL_SERVICE: value.cloudflare?.tunnelService ?? "",
3277
3500
  FZ_REALTIME_WORKER_SCRIPT: value.realtime?.workerScriptName ?? "",
3278
3501
  FZ_REALTIME_ENDPOINT: value.realtime?.endpoint ?? "",
3279
- FZ_REALTIME_PRODUCER: value.realtime?.producer ?? ""
3502
+ FZ_REALTIME_PRODUCER: value.realtime?.producer ?? "",
3503
+ FZ_PLATFORM_INITIAL_INVENTORY: value.initialInventory ? JSON.stringify(value.initialInventory) : ""
3280
3504
  };
3281
3505
  return `# Generated by fz bootstrap platform. Non-secret coordinates only.
3282
3506
  ` + Object.entries(entries).map(([key, entry]) => `${key}=${systemdValue(key, entry)}`).join(`
@@ -3458,15 +3682,15 @@ var replaceLink = (path2, target) => {
3458
3682
  renameSync6(pending, path2);
3459
3683
  };
3460
3684
  var secureRelease = (path2, uid, gid) => {
3461
- const visit = (current) => {
3462
- const metadata = lstatSync(current);
3685
+ const visit = (current2) => {
3686
+ const metadata = lstatSync(current2);
3463
3687
  if (metadata.isSymbolicLink())
3464
3688
  throw new Error("release contains a symbolic link");
3465
- chownSync(current, uid, gid);
3466
- chmodSync5(current, metadata.isDirectory() ? 365 : 292);
3689
+ chownSync(current2, uid, gid);
3690
+ chmodSync5(current2, metadata.isDirectory() ? 365 : 292);
3467
3691
  if (metadata.isDirectory())
3468
- for (const name of readdirSync3(current))
3469
- visit(join5(current, name));
3692
+ for (const name of readdirSync3(current2))
3693
+ visit(join5(current2, name));
3470
3694
  };
3471
3695
  visit(path2);
3472
3696
  };
@@ -3719,11 +3943,11 @@ var runProvisionOperation = async (operation) => {
3719
3943
  }
3720
3944
  if (operation.kind === "ensure-git-identity") {
3721
3945
  const key = "/run/forgezero-git-deploy-key";
3722
- const publicKey = `${key}.pub`;
3946
+ const publicKey2 = `${key}.pub`;
3723
3947
  try {
3724
3948
  if (!existsSync8(operation.credential) || lstatSync2(operation.credential).size < 1) {
3725
3949
  rmSync7(key, { force: true });
3726
- rmSync7(publicKey, { force: true });
3950
+ rmSync7(publicKey2, { force: true });
3727
3951
  let result = await fixed(["/usr/bin/ssh-keygen", "-q", "-t", "ed25519", "-N", "", "-C", "forgezero-compute", "-f", key]);
3728
3952
  if (result.exitCode !== 0)
3729
3953
  return result;
@@ -3747,7 +3971,7 @@ var runProvisionOperation = async (operation) => {
3747
3971
  return { stdout: "", exitCode: 0 };
3748
3972
  } finally {
3749
3973
  rmSync7(key, { force: true });
3750
- rmSync7(publicKey, { force: true });
3974
+ rmSync7(publicKey2, { force: true });
3751
3975
  }
3752
3976
  }
3753
3977
  if (operation.kind === "ensure-bootstrap-ssh-identity") {
@@ -3941,7 +4165,7 @@ import { dirname as dirname8, isAbsolute, resolve as resolve6 } from "node:path"
3941
4165
  var BOOTSTRAP_BUNDLE_FORMAT = 1;
3942
4166
  var BOOTSTRAP_BUNDLE_KIND = "forgezero-api-git-bundle";
3943
4167
  var MAX_BOOTSTRAP_BUNDLE_BYTES = 512 * 1024 * 1024;
3944
- var branchName = (value) => {
4168
+ var bootstrapBundleBranch = (value) => {
3945
4169
  if (typeof value !== "string" || !/^[A-Za-z0-9](?:[A-Za-z0-9._/-]{0,126}[A-Za-z0-9])?$/.test(value) || value.includes("..") || value.includes("//") || value.startsWith("-")) {
3946
4170
  throw new Error("bootstrap bundle branch is malformed");
3947
4171
  }
@@ -3958,7 +4182,7 @@ function parseBootstrapBundleManifest(value) {
3958
4182
  if (source.format !== BOOTSTRAP_BUNDLE_FORMAT || source.kind !== BOOTSTRAP_BUNDLE_KIND) {
3959
4183
  throw new Error("bootstrap bundle manifest format is unsupported");
3960
4184
  }
3961
- branchName(source.branch);
4185
+ bootstrapBundleBranch(source.branch);
3962
4186
  if (typeof source.revision !== "string" || !/^[a-f0-9]{40}$/.test(source.revision)) {
3963
4187
  throw new Error("bootstrap bundle revision must be an exact lowercase Git commit");
3964
4188
  }
@@ -1,7 +1,13 @@
1
1
  import { type PlatformBootstrapConfig } from './bootstrap';
2
+ import { type PlatformGenesisGuest } from './platform-genesis';
2
3
  export interface PlatformGenesisNodeConfigInput {
3
4
  nodeHostname: string;
4
5
  cloudflareHandoffFile: string;
5
6
  }
7
+ export interface PlatformGenesisRegionInput {
8
+ label: string;
9
+ country: string;
10
+ city?: string;
11
+ }
6
12
  /** Expand one reviewed common template into the exact three genesis hosts. */
7
- export declare function platformGenesisBootstrapConfigs(template: PlatformBootstrapConfig, nodes: readonly PlatformGenesisNodeConfigInput[]): readonly PlatformBootstrapConfig[];
13
+ export declare function platformGenesisBootstrapConfigs(template: PlatformBootstrapConfig, guests: readonly PlatformGenesisGuest[], nodes: readonly PlatformGenesisNodeConfigInput[], metalHostname: string, region: PlatformGenesisRegionInput): readonly PlatformBootstrapConfig[];
@@ -1,28 +1,27 @@
1
1
  import type { RemoteProvisionClaim } from './provisioning-pull';
2
- export declare const PLATFORM_GENESIS_ENVIRONMENTS: readonly ["production", "development"];
3
- export type PlatformGenesisEnvironment = (typeof PLATFORM_GENESIS_ENVIRONMENTS)[number];
2
+ /**
3
+ * One reviewed guest request. The Metal Agent does not know or infer an
4
+ * environment, product tier, tenant, or development shape: all differences are
5
+ * desired-state coordinates supplied by the same authority that requests the
6
+ * compute.
7
+ */
4
8
  export interface PlatformGenesisGuest {
5
9
  name: string;
6
10
  address: string;
7
- cpuPoolKey: string;
11
+ imageKey: string;
12
+ cpuPoolKey?: string;
8
13
  physicalCores: number;
9
14
  vcpu: number;
10
15
  memoryGib: number;
11
16
  diskGib: number;
12
17
  egressGuaranteedMbps: number;
13
18
  egressBurstMbps: number;
19
+ confidential: boolean;
14
20
  }
15
- /** Package-owned provisioning coordinates for the exact three-node platform seed. */
16
- export declare const PLATFORM_GENESIS_FLEETS: Record<PlatformGenesisEnvironment, readonly PlatformGenesisGuest[]>;
17
- /**
18
- * The disposable Community acceptance fleet adds one ordinary post-genesis
19
- * Coordinator/DBServer host. It is deliberately not part of the three-member
20
- * platform seed and never acquires Agency authority from this provisioning
21
- * claim. The rehearsal controller installs that database role later.
22
- */
23
- export declare const DEVELOPMENT_COMMUNITY_REHEARSAL_GUEST: PlatformGenesisGuest;
24
- export declare function platformGenesisClaims(environment: PlatformGenesisEnvironment, sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
25
- /** Exact disposable four-host development fleet: three seed guests plus n4. */
26
- export declare function platformCommunityRehearsalClaims(sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
27
- /** Exact inverse of the disposable four-host rehearsal claims. */
28
- export declare function platformCommunityRehearsalDeletionClaims(sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
21
+ export declare function validatePlatformGenesisGuests(guests: readonly PlatformGenesisGuest[], expectedCount?: number): readonly PlatformGenesisGuest[];
22
+ /** Convert reviewed desired state into the ordinary Metal provisioning claim. */
23
+ export declare function platformGenesisClaims(guests: readonly PlatformGenesisGuest[], sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
24
+ /** Add one explicitly reviewed disposable node to the same three guest requests. */
25
+ export declare function platformCommunityRehearsalClaims(seedGuests: readonly PlatformGenesisGuest[], rehearsalGuest: PlatformGenesisGuest, sshPublicKeys: readonly string[]): readonly RemoteProvisionClaim[];
26
+ /** Exact inverse of the reviewed disposable four-host request. */
27
+ export declare function platformCommunityRehearsalDeletionClaims(seedGuests: readonly PlatformGenesisGuest[], rehearsalGuest: PlatformGenesisGuest): readonly RemoteProvisionClaim[];