Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3f47d0c
CENSUS-IMAGE 0A: one seeded-image derivation with a measured identity…
Sep 19, 2026
48b85db
srv3 diagnostic: match the optional sha256 token instead of casting it
Sep 19, 2026
4f73d52
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 19, 2026
e16918e
Witness fixes from the floor typecheck: optional and method-surface e…
Sep 19, 2026
0a3703a
Census program: quote through posix_single_quote; declare the string-…
Sep 19, 2026
6dd390c
Review 68615: absent vs unreadable image, declared builder-revision c…
Sep 19, 2026
dd1385d
Census image: declare the publish/resolve frontier and its consumers …
Sep 19, 2026
bbda764
coreutils_stat: import String from its declaring module (floor Ambigu…
Sep 19, 2026
07bd82c
Review 68664: derive the census tty from one row; the BMC-probe fixtu…
Sep 19, 2026
f0d9d61
coreutils_stat: name the declaring module for Unit and the optional c…
Sep 19, 2026
56655cf
Census witness: declare its imports explicitly (review 68712)
Sep 20, 2026
695d83d
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 20, 2026
f24adf1
Merge origin/main into session/sleek-ferret-265; review 68732: xorris…
Sep 20, 2026
7f9e9da
Review 68762: date the mapped files, and type the reproducibility pre…
Sep 20, 2026
ae23a2c
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 20, 2026
9966cad
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 20, 2026
7f42cf5
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 20, 2026
4c076e4
chore: regenerate drifted generated artifacts (ci auto-heal)
gunbai-bot[bot] Sep 20, 2026
b29931d
Review 68870: the marker field names the boot id it carries; the cons…
Sep 20, 2026
e7e20d6
Merge remote-tracking branch 'origin/session/sleek-ferret-265' into s…
Sep 20, 2026
d0d18e1
Census witness: the ordering claim's needles derive from the envelope…
Sep 20, 2026
b643d50
The ARGV false-green claim is now actually discriminating (measured b…
Sep 20, 2026
8e0145c
Merge remote-tracking branch 'origin/main' into session/sleek-ferret-265
Sep 20, 2026
3571045
machine_intake: bind the capture envelope and the historical stage map
Sep 20, 2026
6107b6a
Merge origin/main; renumber census wet route-gap chunk to 20
Sep 20, 2026
2f2d272
Enrol all six census wet claims; fix the workload positive control
Sep 20, 2026
bc9b84a
Derive the workload chunk paths from the dir row; model the footprint
Sep 20, 2026
99f74b0
One spawn per workload case
Sep 20, 2026
7b364fc
Merge origin/main; carry both sides of the nbd actuator-step change
Sep 20, 2026
dd42f3f
Delete the dangling historical_binding_names
Sep 20, 2026
8cc7dd0
Give the capture identity a consumer; fix the NewlyIntroduced trap
Sep 20, 2026
9ab8c6f
Compare run identity by constructor and value, not projected text
Sep 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dag/extdeps/os/ubuntu_autoinstall.dag
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,14 @@ type UbuntuAutoinstallPayload {
ssh_password_auth: Bool
storage_policy: AutoinstallStoragePolicy
}

// A LIVE-SESSION autoinstall: upstream's `early-commands` run in the live installer environment
// before any other autoinstall step, and `interactive-sections: ["*"]` hands every section after them
// to a human. So the commands are the whole unattended content of the seed, and nothing that writes
// storage runs unless someone at the console drives it. Both keys and their semantics are the
// autoinstall reference's (module anchor); the type carries no identity or storage because an
// all-interactive session asks for them at the console instead.
type UbuntuAutoinstallLiveCommands {
autoinstall_version: Int
early_commands: List<NonEmptyStr>
}
160 changes: 118 additions & 42 deletions dag/extdeps/provisioning/ubuntu_seeded_install_media.dag
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
module extdeps.provisioning.ubuntu_seeded_install_media

import std.types { NonEmptyStr, String }
import std.content_hash { ContentHash }
import std.content_hash { content_hash_atom, content_hash_combine_structural, content_hash_tagged }
import extdeps.provisioning.ubuntu_install_media {
UbuntuInstallMediaArtifactRow,
ubuntu_install_media_artifacts_dir,
}
import extdeps.os.ubuntu_autoinstall { UbuntuAutoinstallPayload }
import std.types { Int, List, NonEmptyStr, String }
import std.content_hash { Fnv1a64Structural, content_hash_atom, content_hash_combine_structural, content_hash_tagged_structural }
import extdeps.provisioning.ubuntu_install_media { UbuntuInstallMediaArtifactRow }
import extdeps.external_authority { ExternalAuthority }
import extdeps.uri { Uri, Https }

Expand All @@ -18,15 +13,62 @@ data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
}
}

type UbuntuSeededInstallMediaFlavor = | UbuntuLiveServerSeeded
// A file the NoCloud seed directory carries beside user-data and meta-data. The seed directory is
// the medium's only payload channel that needs no network at runtime, so a program the seed runs
// rides here rather than being fetched.
type NoCloudSeedFile {
name: NonEmptyStr
content: NonEmptyStr
}

type UbuntuSeededInstallMediaArtifactRow {
// WHAT A DERIVED SEEDED IMAGE IS BUILT FROM, and nothing else: every field below reaches the output
// bytes, so each one is in the derivation key. The payload is a PARAMETER -- an install autoinstall
// (srv3) and a live-session census program (Mt. Collins) are both a rendered user-data body plus seed
// files, rendered by their own layer; this module does not know which it is carrying. The volume id
// is a parameter because it decides the block-device label the booted host reports, so a consumer
// that checks the boot medium must expect the derived label, never the stock one.
type UbuntuSeededInstallMediaBuildInput {
stock_artifact: UbuntuInstallMediaArtifactRow
autoinstall: UbuntuAutoinstallPayload
autoinstall_user_data_body: NonEmptyStr
grub_kernel_cmdline: NonEmptyStr
nocloud_dir_on_iso: NonEmptyStr
content_hash: ContentHash
user_data_body: NonEmptyStr
seed_files: List<NoCloudSeedFile>
grub_kernel_cmdline: NonEmptyStr
volume_id: NonEmptyStr
pinned_dates: SeededInstallMediaPinnedDates
image_stem: NonEmptyStr
builder_revision: NonEmptyStr
}

// THE DATES ARE PINNED SO THAT IDENTICAL INPUTS CAN REPRODUCE IDENTICAL BYTES, AND THAT IS A BET
// UNTIL A BUILD RUNS (DESIGN §4d: an inference is typed as a bet, not promoted). What is established:
// the replay stamps the build instant into the volume descriptors and into mapped files, so WITHOUT
// pinning a rebuild of the same inputs measures a different digest. What is NOT established: that
// pinning these two dates is SUFFICIENT for byte-identical output -- xorriso may carry other
// build-varying state, and the ordering these commands rely on (both -volume_date commands after the
// -map commands, so freshly mapped files are covered) is read off the tool's left-to-right execution
// rather than measured. WHAT WOULD SETTLE IT: the srv2 wet control named in
// gunbc.machine_intake_mtcollins1_census_image -- build twice from one input, compare the two measured
// digests, and change one seed byte and compare again.
//
// NOTHING SILENTLY DEPENDS ON THE BET. If a rebuild is not byte-identical it produces a DIFFERENT
// digest, so it publishes under a different name; create-only publication refuses nothing and
// replaces nothing, and the derivation record names whichever bytes were actually built. The cost of
// the bet being wrong is a second published image, not a wrong one.
//
// uuid is xorriso's 16-digit volume date (it is also the medium's blkid UUID); file_date is the
// -alter_date timestring applied to every file.
type SeededInstallMediaPinnedDates {
volume_uuid: NonEmptyStr
file_date: NonEmptyStr
}

// THE IDENTITY IS THE MEASURED OUTPUT, not this. The build key names the derivation (which inputs,
// which builder) so a later reader can find what was built from them; the published name carries the
// sha256 of the bytes the replay actually wrote, read after the build.
type UbuntuSeededInstallMediaBuilt {
build_key: NonEmptyStr
output_digest: NonEmptyStr
image_name: NonEmptyStr
}

// The ds= NoCloud seedfrom carries a ';' (e.g. ds=nocloud;s=<path>). In a grub.cfg linux line ';' is grub's command separator, so the arg MUST be double-quoted or grub truncates the cmdline at ';' and the kernel never sees s=<seedfrom> — autoinstall then falls to interactive. These builders emit grub cmdline strings (injected by the remaster sed), so they quote the ds arg here; the List<KernelCmdlineArg> grub path quotes structurally in grub_cmdline_arg_render.
Expand All @@ -42,46 +84,80 @@ fn ubuntu_seeded_install_media_default_nocloud_dir(hostname: NonEmptyStr) -> Non
concat("nocloud/", hostname as String) as NonEmptyStr
}

fn seeded_install_media_content_hash(
stock_content_sha256: NonEmptyStr,
autoinstall_user_data_body: NonEmptyStr,
grub_kernel_cmdline: NonEmptyStr,
nocloud_dir_on_iso: NonEmptyStr,
) -> ContentHash {
content_hash_tagged(
tag: "ubuntu-seeded-install-media/v2",
fn seeded_install_media_seed_file_key(file: NoCloudSeedFile) -> Fnv1a64Structural {
content_hash_combine_structural(
content_hash_atom(value: file.name),
content_hash_atom(value: file.content),
)
}

fn seeded_install_media_build_key(input: UbuntuSeededInstallMediaBuildInput) -> NonEmptyStr {
let seed = fold(
input.seed_files,
init: content_hash_combine_structural(
content_hash_atom(value: input.nocloud_dir_on_iso),
content_hash_atom(value: input.user_data_body),
),
f: (acc, file) => content_hash_combine_structural(acc, seeded_install_media_seed_file_key(file: file)),
)
let boot = content_hash_combine_structural(
content_hash_combine_structural(
content_hash_atom(value: input.grub_kernel_cmdline),
content_hash_atom(value: input.volume_id),
),
content_hash_combine_structural(
content_hash_atom(value: input.pinned_dates.volume_uuid),
content_hash_atom(value: input.pinned_dates.file_date),
),
)
content_hash_tagged_structural(
tag: "ubuntu-seeded-install-media/v3",
payload: content_hash_combine_structural(
content_hash_combine_structural(
content_hash_combine_structural(
content_hash_atom(value: stock_content_sha256),
content_hash_atom(value: autoinstall_user_data_body),
),
content_hash_atom(value: grub_kernel_cmdline),
content_hash_atom(value: input.stock_artifact.content_sha256 as NonEmptyStr),
content_hash_combine_structural(seed, boot),
),
content_hash_combine_structural(
content_hash_atom(value: input.image_stem),
content_hash_atom(value: input.builder_revision),
),
content_hash_atom(value: nocloud_dir_on_iso),
),
)
).digest as NonEmptyStr
}

fn ubuntu_seeded_install_media_filename(artifact: UbuntuSeededInstallMediaArtifactRow) -> NonEmptyStr {
// Sixteen hex digits of the output sha256 name the image: enough to be unique across every image
// this fleet will ever build, short enough to read on a BMC's virtual-media page. The full digest
// travels in UbuntuSeededInstallMediaBuilt and is what every read-back compares.
data seeded_install_media_name_digest_width: Int = 16

fn ubuntu_seeded_install_media_image_name(image_stem: NonEmptyStr, output_digest: NonEmptyStr) -> NonEmptyStr {
concat(
concat(
concat("ubuntu-", artifact.stock_artifact.point_release as String),
"-live-server-",
),
concat(
concat(artifact.autoinstall.identity.hostname as String, "-seeded.iso"),
),
image_stem as String,
"-",
substring(s: output_digest as String, start: 0, end: seeded_install_media_name_digest_width),
".iso",
) as NonEmptyStr
}

fn ubuntu_seeded_install_media_install_path(artifact: UbuntuSeededInstallMediaArtifactRow) -> NonEmptyStr {
fn ubuntu_seeded_install_media_built(input: UbuntuSeededInstallMediaBuildInput, output_digest: NonEmptyStr) -> UbuntuSeededInstallMediaBuilt {
UbuntuSeededInstallMediaBuilt {
build_key: seeded_install_media_build_key(input: input),
output_digest: output_digest,
image_name: ubuntu_seeded_install_media_image_name(image_stem: input.image_stem, output_digest: output_digest),
}
}

// The derivation record: build key -> measured output digest. It is how a consumer that did not run
// the build (an actuator in another process) finds the image the inputs it holds produced, and every
// consumer re-measures the named file against the recorded digest before trusting it.
fn ubuntu_seeded_install_media_record_path(dir: NonEmptyStr, input: UbuntuSeededInstallMediaBuildInput) -> NonEmptyStr {
concat(
concat(ubuntu_install_media_artifacts_dir() as String, "/"),
ubuntu_seeded_install_media_filename(artifact: artifact) as String,
dir as String, "/.", input.image_stem as String, ".", seeded_install_media_build_key(input: input) as String, ".built",
) as NonEmptyStr
}

fn ubuntu_seeded_install_media_part_path(install_path: NonEmptyStr) -> NonEmptyStr {
concat(install_path as String, ".part") as NonEmptyStr
fn ubuntu_seeded_install_media_staging_path(dir: NonEmptyStr, input: UbuntuSeededInstallMediaBuildInput) -> NonEmptyStr {
concat(
dir as String, "/.", input.image_stem as String, ".", seeded_install_media_build_key(input: input) as String, ".staging",
) as NonEmptyStr
}
Loading