canary-apt Part B: drive the §7 functional gates through the real pkgops issuer - #76
Merged
Merged
Conversation
… issuer Swap the §7 functional gates from the rab-exercise oracle to the real pkgops public path, per docs/pkgops-vm-gate-plan.md Part B. A thin VM-only launcher apt-issue (apt-issue.sh -> apt-issue.R) recomputes the preview via pkgops::apt_<verb>_preview(), compares the caller-supplied resource/plan_hash byte-for-byte (never trusting caller hash data), commits via pkgops::apt_<verb>(), and prints one RESULT line in the rab-exercise grammar with matching exit codes (0 persisted / 1 pre-intent / 3 left-open), so every gate assertion is unchanged. The split is deliberate and preserves all assertions: - functional gates run through real pkgops (apt-issue). G9/G-OWN surface as pkgops PREVIEW-SIDE refusals (no intent opened; outcome=preview_refused), not broker-redemption refusals. - G12/G13/G14 (bad/replayed/stale receipt injection) and G15 (a package arg to the nullary apt.update entrypoint) keep calling rab-exercise directly: they inject inputs the pkgops issuer would never construct. - G11a/G11b call pkexec directly (entrypoint-isolation, below both). install-apt-stack.sh now installs the R stack in the guest (R 4.6 + janssonr + pkgstate + runix + pkgops from staged sources) and the apt-issue launcher, with verify-surface checks. build-and-stage.sh git-archives the three R sources from five clean pinned trees. redact.jq projects the Part A durable post-state fields (observed/changed/state_changed/observed_failed/authorized_via) so the durable-record round-trip is visible; secrets still never leave the guest. CI: the canary-apt-payload job now also R-parses deploy/canary-apt/*.R (deploy/ is .Rbuildignore'd, so R CMD check never sees apt-issue.R).
…er statuses At PREVIEW time only package_not_owned / held / protected_package are genuine planner policy refusals (the statuses the contract pins a plan digest to besides ok), so only those emit outcome=preview_refused / exit 0. Previously the launcher tested the full commit-time CLOSED set, wrongly reporting resolve_failed, internal, and commit-only statuses as persisted refusals despite no intent being opened. Any non-refusal condition at preview time now has no committable intent and exits as a pre-intent failure (exit 1), matching the rab-exercise grammar.
Contributor
Author
|
Part B authoritative run 4 drove through this harness (real |
TroyHernandez
marked this pull request as ready for review
August 20, 2026 18:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
HELD draft — no VM run until this and the pkgops fix (#9) are reviewed and green. No provisioning, no
troy-g5activity.Implements Part B of
docs/pkgops-vm-gate-plan.md: the disposable-VM canary now drives the §7 functional gates through the real pkgops public path instead of therab-exerciseoracle. This is a harness/CI/docs change only —deploy/is.Rbuildignored and no runix package code changes, so no version bump.The launcher
apt-issue(apt-issue.sh→apt-issue.R, VM-only, never packaged) runs unprivileged asaptbot:pkgops::apt_<verb>_preview();resource/plan_hashas expected values, compared byte-for-byte before any commit (never trusts caller hash data);pkgops::apt_<verb>(preview);RESULTline in therab-exercisegrammar with the same exit codes (0persisted /1pre-intent /3left-open), so every gate assertion is unchanged;The split (all assertions preserved)
apt-issue). G9 (protected) and G-OWN (not-owned) surface as pkgops preview-side refusals (apt_<verb>_preview()raises before any intent opens →effect_issued=false,outcome=preview_refused, exit 0). They are not broker-redemption refusals.apt.updateentrypoint) →rab-exercisedirectly: inputs the pkgops issuer would never construct.pkexecdirectly.Supporting changes
install-apt-stack.sh: installs the R stack in the guest (R 4.6 +janssonr+pkgstate+runix+pkgopsfrom staged sources) + theapt-issuelauncher, with verify-surface checks.build-and-stage.sh:git archives the three R sources; now refuses unless five trees are clean (broker, pkgexec, runix, pkgstate, pkgops).redact.jq: projects the Part A durable post-state fields (observed/changed/state_changed/observed_failed/authorized_via) so the durable-record round-trip is visible in evidence; secrets still never leave the guest.canary-apt-payload: now also R-parsesdeploy/canary-apt/*.R(R CMD checknever seesapt-issue.Rsincedeploy/is.Rbuildignored).Dependency
Installs pkgops from the #9 + Part A branch (the exported
apt_<verb>()commit API lives only on #9). #9 carries the.ensure_cidfix so a mid-flight kill (G-INT) yieldsoutcome=open/exit 3 with the session cid attached.Depends on: cornball-ai/pkgops#9