feat(core): publish a journal phase change only under exclusive admission
User description
What
A journal phase change is now published only by commit_phase_transition, which takes the installation's ExclusiveAdmissionGuard by mutable borrow. The ordinary progress checkpoint no longer carries a phase change.
commit_phase_transitioncommits the root below that admission; an admission that does not guard the root of its layout is refused asNotAdmittedbefore anything is read. A shared guard, and a shared reference to the exclusive guard, do not compile (twocompile_faildoctests paired with one that compiles).- The progress checkpoint, the binding advance and the journal-level checkpoint publish refuse a successor that changes the phase (
PhaseChangeNotACheckpoint); the transition refuses one that keeps it (NotAPhaseChange). Both refusals precede the first journal byte. - The root classifies the advance with a new
BindingStep::PhaseTransition, so a generation promoted directly becomes authoritative only through the transition. Capture, renewal and takeover keep their own relations. - The conversion driver's two phase changes (
enter_convert,finish_convert) use the held form of the transition; its behaviour is unchanged.
Why
The owner confirmed D1(a), D2(a) and D3 on #359 for exactly one bounded Gate 4E E2 follow-up slice: typed exclusive protection of real phase changes, separated from ordinary progress checkpoints. Contract §10.3 named this as the step that makes the exclusive-admission requirement of a phase change mechanical.
Evidence
- Hosted CI is the authority. Locally, only
cargo clippy --all-targets -D warningsfor the crate,cargo fmt --check, the affected test binaries (the new file, root binding, journal durable, journal route, conversion entry) and the threecommit_phase_transitiondoctests were run, one job at a time. - New
tests/gate4e_phase_transition_test.rs: success under exclusive admission, both refusals writing nothing, an admission for another root, the directly promoted phase change (refused by the advance and the checkpoint, adopted without a journal write only by the transition), the journal-level publishers, and shared/exclusive admission excluding each other. - Existing tests that moved the phase through the checkpoint are migrated: the root-binding fixture picks the path by the committed phase, the binding-advance scenario keeps the phase of its bootstrap revision, and one rival candidate in the journal-durable tests goes through the transition publisher. Refusal tests keep their errors, because both successor relations run the progress relation first.
- The two compile_fail doctests were checked to fail with
E0308on the guard parameter, not on an unrelated error.
Not in scope
No producer of a binding, no PREPARE/DONE window, no change to the capture, takeover or renewal writers, no writer journal locator, no E3, no Gate 5 or later. The E1 barrier is unchanged.
Part of #359. Owner: #922 / QNB-168.
Summary by Sourcery
Require exclusive admission for journal phase changes while keeping ordinary progress checkpoints phase-preserving.
New Features:
- Add an exclusively admitted phase-transition commit path for publishing journal phase changes and making them authoritative.
Bug Fixes:
- Prevent ordinary checkpoints, binding advances, journal checkpoint publishers, and raw production root commits from bypassing exclusive phase-transition requirements.
Enhancements:
- Enforce distinct successor rules for progress checkpoints and phase transitions, including root admission validation and typed admission-mode guarantees.
- Route conversion phase changes through the protected transition path while preserving existing conversion behavior.
Documentation:
- Document the Gate 4E exclusive phase-transition contract, its limitations, and the associated evidence.
Tests:
- Add coverage for successful and rejected phase transitions, no-write refusals, foreign and conflicting admissions, direct promotion, publisher behavior, and alias retargeting.
Chores:
- Restrict the raw root commit API to the test-support feature.
Summary by cubic
Publishes a journal phase change only under the installation's exclusive admission: the new commit_phase_transition takes ExclusiveAdmissionGuard by mutable borrow, and the progress checkpoint, binding advance, and journal-level checkpoint publish refuse a successor that changes the phase.
- The root commit event is typed by its admission's mode (
AdmittedRootCommitGuard<'_, Mode>), so the held transition takes the exclusive event and a shared guard or bare root lock cannot reach it. commit_phase_transitionresolves the root's canonical path once at admission proof and uses it for all reads and writes, so a retargeted alias cannot redirect the commit; an admission for another root is refused asNotAdmitted.- Refusals (
PhaseChangeNotACheckpoint,NotAPhaseChange) precede the first journal byte; the transition adopts an identical directly-promoted candidate without a journal write, and the phase-transition publisher refuses a bootstrap, which stays with the ordinary publisher. - The raw
commit_root, which publishes whatever binding it is given, is now exported only with the test-onlytest-supportfeature, so a bare root lock can no longer make a directly promoted phase change authoritative through it. - The conversion driver's
enter_convertandfinish_convertuse the held transition form with unchanged behavior; capture, takeover, and renewal writers are untouched. - New
gate4e_phase_transition_test.rscovers success, both refusals, foreign admission, direct promotion, the journal-level publishers, shared/exclusive exclusion, and Unix-only alias redirection, the alias cases in their own module. - Recovery of a transition that a crash interrupts after the anchor is prepared is completed forward by
recover_root, which asks for no exclusive admission; that point stays open (#359).
Summary by CodeRabbit
- New Features
- Phase changes can now be committed through exclusive installation admission, with the root linked to the new journal revision.
- Conversion phase changes use this process while retaining their existing behavior.
- Bug Fixes
- Progress checkpoints and binding updates now reject phase changes, while phase transitions reject updates that keep the same phase.
- Invalid operations are refused before journal data is written.
- Documentation
- Secure storage guidance now describes admission requirements and rules for phase changes and progress updates.
CodeAnt-AI Description
Require exclusive admission before changing a journal phase
What Changed
- Journal phase changes can become authoritative only through a commit holding the installation’s exclusive admission; ordinary checkpoints reject phase changes before writing journal data.
- The transition rejects updates that keep the same phase or use an admission for a different root.
- Conversion phase changes use the protected transition, with conversion behavior unchanged.
- Production callers can no longer use the raw root commit to bypass phase-transition checks.
Impact
✅ Phase changes cannot overlap ordinary operations
✅ Invalid phase updates write no journal data
✅ Wrong-root admissions cannot commit a transition
💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
@codeant-ai ask: Your question here
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
@codeant-ai ask: Can you suggest a safer alternative to storing this secret?
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
@codeant-ai: Your feedback here
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
@codeant-ai: Do not flag unused imports.
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
@codeant-ai: review
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.