Skip to content

Prepare disabled Mint media authentication and offline console workflow - #77

Merged
rdpollard merged 3 commits into
mainfrom
infra/mint-media-console-manual
Oct 18, 2026
Merged

rdpollard merged 3 commits into
mainfrom
infra/mint-media-console-manual

Conversation

@rdpollard

@rdpollard rdpollard commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Prepares a separate, disabled-by-default manual workflow for the reviewed Mint media-authentication and offline console-plan helpers. It does not activate or execute them.

The fixed workflow requires main source/workflow SHA approval, an independently reviewed caller/helper/key bundle hash, separate preparation flags, protected mint-host-access approval and the restricted sde-mint-isolated runner group. No dispatch inputs, arbitrary URLs/commands, reruns, guest launch, disk creation or package executor are exposed. The caller verifies bounded source snapshots before loading ports, runs the merged signature/digest/resource/ownership gates, and emits bounded sanitized evidence after descriptor closure. TERM/INT handling, source descriptor cleanup, complete manifest reads and failure sanitization include reviewed fault checks.

Automatic hosted CI runs mocked/static checks and lint only. Exact scope additions cover the workflow/caller/test; the complete ten-file diff skips application jobs on PR and future infrastructure-only main pushes. Mixed application, signing-key and unknown paths retain normal application CI. Existing live inventory, native-fixture and application workflow definitions are unchanged.

Validation: 86 local mocked/static checks passed (39 helper, 30 caller/workflow, 8 policy, 9 scope), focused actionlint and whitespace checks passed. Native cancellation/child cleanup, mirror/GPG/filesystem behavior, evidence retrieval and actual authentication remain unvalidated. Historical #72 findings are preserved.

Keep this PR draft and unmerged. No activation settings, runner registration/start, dispatch, media downloads, guest execution, PR #73 merge, application builds/packages or releases are authorized. Before any future run, the exact runner-group workflow restriction and environment controls must be reviewed separately; labels are routing only, and prior self-review exceptions are not reusable authorization.

Review follow-up 5ac0559 preserves the runner cleanup marker in the fixed curl/GPG child environment without propagating unrelated credentials or injection settings. Mocked coverage verifies marker presence/absence and synthetic termination through child cleanup. This is a best-effort fallback, not native cancellation or authentication proof. Dispatch gates and activation settings are unchanged.

Copy link
Copy Markdown
Member Author

Automatic CI verified on exact head c587dc1:

  • Preparation policy/mock checks: success (run 39098126260).
  • Static fixture workflow lint: success; Windows and Mint native fixture jobs: skipped (run 39098126206).
  • Application scope check: success; checks/native/update-trust/release: skipped (run 39098126301).

Local checks: all 84 mocked/static checks, focused actionlint and diff whitespace checks passed. The complete eight-file PR diff is within the exact infrastructure allowlist; mixed application, signing-key and unknown-path controls retain application CI. Live inventory, native-fixture and application workflow definitions are unchanged from main.

No manual dispatch, new preparation job, runner operation, activation-setting change, media acquisition, guest execution, application build/package/release or merge was performed. The new workflow is disabled by default and still requires separate reviewed access-control and execution authorization. Native cancellation/cleanup/authentication remain unproven. #77 and #73 remain draft/open/unmerged.

Copy link
Copy Markdown
Member Author

Reviewed and fixed at 5ac0559.

Finding: the reused owned curl/GPG process helper filtered out RUNNER_TRACKING_ID, weakening the runner's independent orphan-process cleanup fallback after forced caller termination. The fixed child environment preserves that opaque marker only when supplied, without logging it or propagating unrelated GitHub credentials, SSH agent settings or loader injection variables. This is cleanup metadata, not authentication authority; SIGKILL/runner/native cleanup correctness remains unproven. The independently approved bundle must include the changed native helper.

Added mocked checks cover tracking-marker presence/absence with the fixed environment and synthetic termination passing through real owned-child kill/wait/descriptor/selector cleanup logic. No process was spawned and no real signal was installed or sent.

Local QA: 86 mocked/static tests passed (39 helper, 30 caller/workflow, 8 policy, 9 scope), focused actionlint and git diff --check passed.

Exact-head CI:

  • policy succeeded (39098388821).
  • scope succeeded; checks/native/update-trust/release skipped (39098388864).
  • workflow-checks succeeded; windows-fixtures/mint-fixtures skipped (39098388819).

The full ten-file diff remains infrastructure-only, with mixed application/key changes retaining normal CI. Workflow gates, live inventory/native-fixture/application definitions and activation settings are unchanged. No dispatch, runner operation, download, guest work, application build/package/release or merge was performed. #73 and #77 remain draft/open/unmerged.

Remaining gates: verify live selected-workflow/group/environment controls and fresh final SHA/bundle before any separately authorized execution. Actual mirror/GPG/filesystem behavior, cancellation/child cleanup, evidence retrieval and media authentication remain native proof obligations. Local diagnostic completion is not authentication safety, cleanup proof, runner deregistration or whole-host restoration.

@rdpollard
rdpollard marked this pull request as ready for review October 18, 2026 04:54
@rdpollard
rdpollard merged commit 05a8142 into main Oct 18, 2026
9 checks passed

Copy link
Copy Markdown
Member Author

Bounded execution authorization packet — preparation only, NOT authorization to execute

PR #77 merged as 05a8142. Post-merge policy/mock checks succeeded (39098701813), and the scope check succeeded with checks/native/update-trust/release skipped (39098701877). PR #73 remains draft/unmerged. No activation settings were changed, runner registered/started, workflow dispatched, media acquired, guest run, application built/packaged or release prepared.

Exact approved-code candidates (do not configure yet):

  • Repository: stormbots/Tactics-Strategy-Dev-Environments.
  • Workflow: .github/workflows/mint-media-console-prep.yml, job prepare.
  • Dispatch ref: main, only while its HEAD remains 05a8142.
  • MINT_PREP_APPROVED_SHA: 05a8142.
  • MINT_PREP_HELPERS_SHA256: 7136fd3a3ed02cac06ef2ba8d10543cf98dc5352cb9e1c8d5184b9365d0a7899.
  • Bundle format: mint-prep-bundle-v1 NUL prefix followed, in caller SOURCES order, by each ASCII path + NUL + decimal byte length + NUL + exact bytes from this commit. The four source snapshots include caller, core, native ports and public key. A changed main SHA, changed source/bundle or rerun invalidates this packet; stop and reassess rather than substitute another ref/hash.

Execution is BLOCKED pending the following live controls and new explicit permission:

  1. Group 3, sde-mint-isolated: selected repositories only this repository; sole selected workflow stormbots/Tactics-Strategy-Dev-Environments/.github/workflows/mint-media-console-prep.yml@refs/heads/main. Replace the historical inventory selection, do not broaden to all workflows. Public-repository access must be checked for this selected repo only. Runner routing label sde-mint-prep is not authorization. Group access API returned 403, so these settings are not independently verified.
  2. Environment mint-host-access: API verified sole deployment branch main, required reviewer rdpollard, admin bypass=false. CURRENT prevent_self_review=false. Restore it before any activation unless/until a newly authorized, single-run exception is explicitly approved. The historical exception and relaxed PR approval rule are not consent. If sole-reviewer execution is later authorized, temporarily permit self-review only for the exact waiting run, have the owner approve that exact SHA/job/operation, and restore protection immediately after approval before runner startup. A second reviewer would avoid that exception.
  3. Repository MINT_PREP_ENABLED must remain unset/false now. The variables API returned 403: current values cannot be independently attested. No variable change was made. Future activation also requires MINT_PREP_ACCESS_READY=verified after live access-control verification and the exact SHA/hash above. Legacy inventory activation remains disabled. No environment/repository secrets or registration token belong in chat or shell history.
  4. A separately authorized fresh ephemeral single-job runner must use the existing dedicated non-sudo sde-runner account on the spare ryan-ThinkCentre-M910q Mint host, only in group sde-mint-isolated. Check the dedicated account/work directory ownership, expected KVM access and absence of an earlier live registration. Register but do not listen until the exact queued run has environment approval. No service registration, sudo, package/dependency installation or token reuse is included.

The one proposed run, only after explicit authorization, would permit:

  • GitHub checkout of the exact approved commit in the dedicated runner work directory, without persisted credentials/submodules/LFS; isolated Python caller with no arguments.
  • Read-only Mint 22.3 x86_64/account/groups/fixed-tool ancestry/resource inspection and /dev/kvm open plus KVM API-12 ioctl. Require >=6 GiB available RAM and >=40 GiB free disk. Missing tools/resources/access cause a stop, not installation or privilege fallback.
  • A fresh run-owned 0700 directory under the dedicated account's passwd home, mint-validation/, with bounded private files and a fresh private GPG keyring. No pre-existing directory reuse, personal-home traversal or broad deletion.
  • Only /usr/bin/curl and /usr/bin/gpg child tools for fixed HTTPS downloads, key import/signature verification and bounded version collection. Fixed source https://mirrors.kernel.org/linuxmint/stable/22.3/: sha256sum.txt, sha256sum.txt.gpg, then linuxmint-22.3-cinnamon-64bit.iso only after metadata authentication. Preserve configured proxy/CA trust and opaque runner tracking, never log credentials/marker. No arbitrary URL or command input.
  • Trust anchor primary fingerprint 27DEB15644C6B3CF3BD7D291300F846BA25BAE09 and repository key SHA-256 565ca5c2e7cf48a60a2f043af7147e27df13d80779948a46f3cceda4e5dcad9b. Require valid signed metadata, no revoked/expired/extra signature, exactly one canonical Cinnamon digest and actual complete-file digest equality. The Cinnamon ISO digest is authenticated during the run; none is invented here.
  • Bounds: 25-minute job; 60 seconds per metadata transfer, 900 seconds for ISO, 20-second connection timeout; <=3 same-origin/same-path HTTPS redirects; one attempt per object, no retries/resume/mirror substitution. Key/checksum <=64 KiB each, signature <=8 KiB, ISO <=6 GiB, owned workspace <=8 GiB monitored budget. Filesystem calls are not hard-real-time; keyring bounds are monitored, not a quota guarantee.
  • Durable report/ownership manifest, sealed authenticated media and offline console plan DATA ONLY (2 vCPUs/4 GiB/30-GiB virtual disk intention, Unix VNC/QMP sockets, no NIC). No QEMU process, VM disk creation, media extraction, guest boot/login, console controller, host networking listener/share, updater/package operation, application build or release.
  • Bounded sanitized <=64 KiB log export identifying source/bundle hashes, Actions run/attempt/job name, actual host facts, media authentication and ownership. No ISO/keyring/raw tool/runner diagnostics artifact upload. Ownership and report persistence, workflow completion, child cleanup, runner deregistration and whole-host restoration remain distinct.

Proposed future ordering (not performed):
A. Verify controls/current HEAD; obtain explicit authorization for the operations and any single-run self-review exception; prepare a fresh offline ephemeral registration.
B. Set prospective SHA/hash/access variables, then enable only MINT_PREP_ENABLED for the approved run. Dispatch exactly this workflow once at main, with no inputs. Record run ID; inspect/cancel any unapproved duplicate before runner startup.
C. Owner approves the exact waiting environment deployment. Restore prevent-self-review before starting the listener. Start only the approved ephemeral runner. The caller rechecks flags at runtime, so do NOT disable MINT_PREP_ENABLED between queuing and execution; keep it true only through this single approved run and reject/leave unapproved duplicates unserved.
D. On completion or stop, disable MINT_PREP_ENABLED immediately, confirm no extra waiting/running dispatch, verify listener exit/removal of local registration and remote group membership, and retain only owned bounded evidence/partial files. Do not re-register, rerun, resume, retry or delete uncertain state automatically. Missing/failed evidence, ownership change, signature/digest mismatch, unsupported native behavior, cancellation or resource bound stops the phase. Graceful signal handling/tracking are best effort; SIGKILL and actual runner cleanup remain unvalidated.

Pass criteria: one genuine signature/digest-authenticated Cinnamon ISO, durable run-bound evidence and an offline non-executed plan, plus separately verified job and runner closeout. No success claim for usable console/guest/updater behavior. Native authentication, filesystem, cancellation/cleanup and evidence retrieval still need observation; mocks are not proof of those properties.

This packet authorizes NOTHING by itself. Current instruction remains preparation only: leave activation disabled, no runner operations/dispatch/download/guest execution, no #73 merge, no application builds/packages/releases.

Reviewed source-file hashes:

  • tests/run_mint_media_console.py: 9581 bytes; SHA-256 979ba47133a10d5138c0b17c8117314c3ce25b03a4f8f500219909d7ff286720.
  • tests/mint_media_console.py: 11738 bytes; SHA-256 f21c2827a68f2494d0d892ec610b3915e30a1da623e109fcb0ac02c8a536c607.
  • tests/mint_media_native.py: 24360 bytes; SHA-256 9d10aefe5f938bc7ef024610c2920b8127df1ef8f1608a31c803b0fe8b471f80.
  • tests/fixtures/linuxmint-iso-signing.asc: 2370 bytes; SHA-256 565ca5c2e7cf48a60a2f043af7147e27df13d80779948a46f3cceda4e5dcad9b.

Copy link
Copy Markdown
Member Author

Stopped native preparation run 39099802574 / job 117593558727:

  • Approved source 05a8142, attempt 1; runner sde-mint-prep-once (196), group sde-mint-isolated (3), user-provided terminal identifies spare ryan-ThinkCentre-M910q.
  • Checkout succeeded. Caller returned: {"pass":false,"reason":"SOURCE_OWNER","ownedRunId":null,"interrupted":false,"nativeGuestTestsExecuted":false,"productionReady":false,"cleanupCorrectness":"NotConfirmed"}.
  • Source review of the exact approved caller identifies SOURCE_OWNER only in source-directory ancestry validation: every directory must be root/current-UID owned and have no group/other write bits. The log does not identify the failing component; no exact cause or permission fix is established yet.
  • That guard precedes bundle validation, helper loading, host collection, UUID/workspace allocation and transfers. Thus this caller did not invoke KVM/host collection, native media tools/downloads or preparation workspace creation. GitHub checkout/setup did perform its ordinary repository/runner file and action-download operations, so this is not a whole-host no-write claim.
  • Terminal evidence shows failed job, removal of local .credentials/.runner and listener exit 0. The runner initially remained remotely listed; owner subsequently confirmed remote removal. Owner also confirmed preparation activation disabled. Those are user-confirmed closeout facts; runner-group/variable APIs remain inaccessible. Environment API independently confirms prevent_self_review=true; no duplicate preparation run was observed. No retries or re-registration occurred.

Native authentication: NotRun; preparation result: failed/stopped. Source-descriptor cleanup is not independently proven by this log; whole-host restoration remains unproven. Retain checkout/diagnostic files, do not change permissions or delete uncertain state. The next minimal diagnostic is read-only UID/mode/owner inspection of the source path and its ancestors, not a rerun. No package/guest/update/build/release operation or #73 merge is authorized.

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