Skip to content

Enforce payload layer-size budget against real history; add bootc signing runbook - #18

Merged
oratis merged 4 commits into
mainfrom
followup/os-layer-and-signing
Aug 2, 2026
Merged

Enforce payload layer-size budget against real history; add bootc signing runbook#18
oratis merged 4 commits into
mainfrom
followup/os-layer-and-signing

Conversation

@oratis

@oratis oratis commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Layer-size budget now actually runs (os-infra review #5)

The layer-SIZE half of test-containerfile-layer-budget.sh had never run against a real image: os-e2e invoked the guard only at the pre-build Validate scripts step, before build-iso.sh produced output/andromeda-v1-history.json. It therefore always emitted ANDROMEDA_CONTAINERFILE_LAYER_SIZE_SKIP reason=no-history-json, leaving the default single-layer ceiling untested — so the real failure mode stayed uncaught: an over-consolidated payload layer overflowing the installer /var/tmp overlay during bootc install (the recent outage).

  • The guard now has count / size / all modes (ANDROMEDA_LAYER_BUDGET_MODE). os-e2e runs count pre-build (static Containerfile DNF-layer floor, no image needed) and a new size step post-build against the real history, placed before the long install so it fails fast.
  • size mode FAILS (does not skip) when the history JSON is missing — the guard can never silently no-op again. all (default) keeps it unit-runnable, skipping size when no image is built.
  • The size check always prints ANDROMEDA_MAX_PAYLOAD_LAYER_BYTES_OBSERVED=<n> threshold=<t> on pass and fail, so the real baseline is greppable from CI logs.
  • Default ceiling set to a 3 GiB headroom value (3221225472) chosen to PASS the known-good image on the first post-build run while still catching gross over-consolidation. A comment and the failure message tell maintainers to read the OBSERVED line and tighten toward OBSERVED + margin once CI reports the real max.

The real observed baseline must be read from this PR's os-e2e run and the threshold tightened in a follow-up if warranted (I cannot build the ISO locally).

bootc signing: documented, NOT activated (security review #4)

Installs point --target-imgref at the mutable, unsigned ghcr.io/oratis/andromeda:edge. A strict signing policy cannot be enabled now: no real key exists and a fail-closed policy.json would reject every registry pull and break the unsigned :edge update flow os-e2e exercises.

  • os/signing/policy.json.example — strict sigstore template (default reject; cosign-verified ghcr.io/oratis/andromeda over docker; local containers-storage/oci/dir still accepted). It lives outside os/files/, so COPY os/files/ / can never install it as /etc/containers/policy.json; the image keeps the Fedora default and :edge pulls are unaffected. The effective enforced policy is unchanged.
  • docs/development/installable-preview.md gains a runbook section (explicitly NOT YET ENFORCED) covering the cosign sign release step and how to activate enforcement once a key exists.
  • Both kickstart --target-imgref comments now point at the template and runbook.

Validation

  • shellcheck os/scripts/*.sh os/installer/*.sh os/files/usr/libexec/* — clean.
  • Guard exercised locally: count-only passes; synthesized andromeda-v1-history.json under threshold passes, over threshold prints OBSERVED and exits non-zero; size mode hard-fails on missing history.
  • os-e2e.yml parses (PyYAML); new size step sits after build, before install.
  • ISO cannot be built in this environment; the observed baseline comes from this PR's os-e2e run.

oratis and others added 4 commits August 1, 2026 21:45
The layer-SIZE half of test-containerfile-layer-budget.sh never actually
ran: os-e2e invoked the guard only at the pre-build "Validate scripts"
step, before build-iso.sh produced andromeda-v1-history.json, so the size
check always emitted ANDROMEDA_CONTAINERFILE_LAYER_SIZE_SKIP and the
default single-layer ceiling was untested against reality. That leaves the
real failure mode uncaught: an over-consolidated payload layer overflowing
the installer /var/tmp overlay during bootc staging (the recent outage).

Split the guard into count/size/all modes (ANDROMEDA_LAYER_BUDGET_MODE):
- count runs pre-build (static Containerfile DNF-layer floor, no image).
- size runs post-build against the real history and FAILS, rather than
  skipping, when the history JSON is missing, so it can never silently
  no-op again.
- all (default) keeps the guard unit-runnable, skipping size when no
  image has been built.

The size check now always prints
ANDROMEDA_MAX_PAYLOAD_LAYER_BYTES_OBSERVED=<n> threshold=<t> on both pass
and fail, so the real baseline is greppable from CI logs. The default
ceiling is lowered to a 3 GiB headroom value chosen to PASS the known-good
image on the first post-build run while still catching gross
over-consolidation; a comment and the failure message direct maintainers
to read the OBSERVED line and tighten toward OBSERVED + margin once CI
reports the real max. os-e2e now runs count pre-build and size post-build
(before the long install so it fails fast).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Installs point --target-imgref at the mutable, unsigned
ghcr.io/oratis/andromeda:edge (security-review.md finding #4). A strict
signing policy cannot be turned on now: no real signing key exists, and a
fail-closed policy.json would reject every registry pull and break the
unsigned :edge update flow that os-e2e exercises.

Ship a template and runbook only, without changing the effective policy:
- os/signing/policy.json.example is a strict sigstore policy (default
  reject; cosign-verified ghcr.io/oratis/andromeda over docker; local
  containers-storage/oci/dir still accepted so offline install and the
  E2E OCI import keep working). It lives outside os/files/ so COPY
  os/files/ / can never install it as /etc/containers/policy.json; the
  image keeps the Fedora default (insecureAcceptAnything) and :edge pulls
  are unaffected.
- installable-preview.md gains a runbook section, explicitly marked NOT
  YET ENFORCED, covering the cosign sign release step and how to activate
  enforcement once a key exists.
- both kickstart --target-imgref comments now point at the template and
  runbook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first post-build guard run on this branch reported
ANDROMEDA_MAX_PAYLOAD_LAYER_BYTES_OBSERVED=1289780224 (~1.20 GiB) for the
known-good 23-layer payload, so the 3 GiB placeholder left 2.5x headroom --
too loose to trip before a consolidated payload transaction overflows the
installer /var/tmp overlay.

Tighten the ceiling to 2 GiB (~1.66x observed): the real image still passes
with room for package growth, while a 2.5 GiB consolidated layer now fails
(it passed under the placeholder).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@oratis
oratis merged commit a2de33f into main Aug 2, 2026
5 checks passed
@oratis
oratis deleted the followup/os-layer-and-signing branch August 2, 2026 04:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant