Repository navigation
refactor(store): own removal mark SQL in mark.rs - #4052
Merged
Merged
Conversation
The 'no live removal names this Environment' condition was pasted into six queries in pull_request, follow and proposal, IDLE_FACTS carried the Project-aware variant, and the merge undo deleted the mark with raw SQL. mark.rs now exposes unmarked, marks_holding and drop_live, and the state literals live there only.
The saved document owns its node vocabulary: SavedServiceIntent.slug is a ServiceName, decoded once with the document, so the store stops re-parsing the same string at each use. The serialized form is unchanged.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
SavedServiceIntent.slug is a String again. Typing it as ServiceName made a stored intent whose slug is not a valid Service Name fail to decode, where main decodes and admits it. Cloud rows cannot be inspected from here, so the stricter decode waits for a data check or a lenient-decode design. Pin the property with a test: a stored slug of "Web", "web_app", "web-" or 64 characters still decodes.
nick-potts
marked this pull request as ready for review
November 10, 2026 13:34
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.
Why
Goal: untangle the
core/workspace so pieces that change together live together, with behavior unchanged. Later agent changes then read less, break less silently and debug faster. This is batch 1 of a 25-batch plan, kept to one small chunk so it lands fast beside other PRs.The
config_removal_markSQL inployz-storewas written by hand in seven modules, with the state literals typed each time. This PR gives it one owner.What changed
removal::marknow owns every statement overconfig_removal_mark. It gainsunmarked,marks_holdinganddrop_live. The state literals come fromstate_textand oneREMOVEDconstant.pull_request,branch::followandbranch::proposalcall these and no longer spell the SQL.verify-removal-marksskill lists the newmark.rshelpers and their callers.environment_intentpins that a stored Service slug that is not a Service Name ("Web","web_app","web-", 64 characters) still decodes.Scope
SavedServiceIntent.slugfromStringtoServiceNameand removed about 30 re-parse sites. It is taken back out of this PR, because the stricter decode leaves behavior worse than main. Main decodes and admits a stored intent with slug"Web","web_app","web-"or a 64-character lowercase slug. With the type change those intents fail to decode (invalid Service Name "Web": a 1-63 character lowercase DNS label). No writer on main is known to produce such a slug, but deployed Cloud rows cannot be inspected from here, and an environment whose stored intent no longer decodes is worse than main. F1 needs a data check on deployed rows, or a lenient-decode design, first.nodes(),node_by_*,volume_of/config_ofandNodeKindsadditions stay for a follow-up. They touch most of the same files as other open PRs.cancel_live. It isdrop_live, because it deletes the live mark and leaves no tombstone. That is not a cancel in the mark's ownCancelledsense.Design bets: bet 8 only, and it is unchanged: a removing Environment is still never listed as open. The Stable promise is untouched. No row, replicated body or serialized shape changes.
Blast Radius
Cloud-side Config Store code only. No Machine behavior changes, so no Boat run. Every read and write behaves as on main.
Verification
cargo clippy -p ployz-store -p ployz-core --all-targets -- -D warningsandcargo fmt --checkare clean on this head.cargo nextest run -p ployz-storefiltered to removal, mark, pull_request, branch and sweep passes on SQLite (286 tests).cargo test -p ployz-core --test environment_intent --test syncandcargo test -p ployz-verify removal_markspass.core/AGENTS.md) was done on the earlier head, before F1 was taken out. It has not been rerun on this head. Theconfig_removal_markstatements are unchanged since then.a_stored_service_slug_that_is_not_a_service_name_still_decodes.Decision log: T11-F2, and why T11-F1 is deferred
T11-F2.
removal::markowns every SQL statement overconfig_removal_mark. It addsunmarked(environment_column)(theNOT EXISTS ... state = 'removing'fragment),marks_holding(environment_column)(the Project-aware scalarIDLE_FACTSuses) anddrop_live, which deletes the live mark for the PR merge undo. State literals come fromstate_text(State::..)inmark.rsonly. Behavior is preserved exactly: the Environment-only copies keep the Environment-only predicate,IDLE_FACTSkeeps the Project-aware one. Teardown deleting marks by cascade stays as it is. Bets touched: bet 8 only, unchanged. Frozen risk: none.T11-F1 (deferred). The idea was to have the saved document carry a Service's name as a
ServiceName, so the store stops re-parsing it. The serde form istry_from/intoString, so JSON stays byte-identical, but the decode becomes strict. Review replaced only/services/0/slugin theenvironment_intentfixture and found that main decodes and admits"Web","web_app", a 64-character lowercase slug and"web-", and the typed head fails to decode them. That is worse than main for any such stored row. It returns after a data check on deployed rows or a lenient-decode design.