Admin Settings: enforce the form field contract before stage D moves cards - #1306
Merged
Paul Lizer (paullizer) merged 2 commits intoAug 19, 2026
Conversation
Admin Settings submits a single form and the backend reads every value by field name, so the set of name attributes is the real contract between the template and route_frontend_admin_settings.py. Renaming or dropping one silently stops that setting from saving: no error is raised, the control still renders, and the value simply never arrives. Every stage of the information architecture rework has been verified against a field-name fingerprint, but that check lived in a scratch script and only ran when someone remembered to run it. Stage D moves 96 cards between tabs, which is exactly when an accidental rename is most likely and least visible. The check is now a functional test with the baseline committed alongside it, so it runs in CI on every commit and protects anyone editing these templates later, not just this migration. Adding settings is unaffected: new field names are reported, not failed. Removing or renaming one requires regenerating the baseline in the same commit via --update-baseline, which turns a silent loss into a reviewed decision. The test also rejects duplicate field names outside the five known radio and checkbox groups. That is the property that stops a mirrored control from submitting its value twice, which the Access and Roles roster in stage E depends on. Both assertions were verified to fail correctly: renaming a field is reported by name, and introducing a duplicate is reported with its count. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The rework spans several pull requests into a staging branch, and the context needed to continue it safely has been living in conversation history and in scratch scripts rather than in the repository. Records what has shipped, how to run each guardrail, the regression baseline of 33 pre-existing failures, the three structural complications found while splitting the template, the locked decisions, and the CI branch filters that must be reverted before the staging branch merges into Development. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
merged commit Aug 19, 2026
2422d86
into
microsoft:feature/admin-settings-ia
11 checks passed
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.
Groundwork before stage D moves any cards. Targets the
feature/admin-settings-iastaging branch.Why now
Admin Settings submits one form, and the backend reads every value by field name. That makes the set of
nameattributes the real contract between the template androute_frontend_admin_settings.py.Renaming or dropping one is uniquely nasty: no error is raised, the control still renders, the form still submits — the value just never arrives. Nothing fails until someone notices a setting stopped sticking.
Every stage of this rework has been verified against a field-name fingerprint, and it has caught nothing so far because the moves have been careful. But that check lived in a scratch script that only ran when I remembered to run it. Stage D moves 96 cards between tabs, which is exactly when an accidental rename is most likely and least visible.
So the check becomes a test, with the baseline committed beside it.
What it enforces
1. No field may silently disappear. Every name in the baseline must still exist.
Adding settings is unaffected — new names are reported, not failed. Removing or renaming one requires regenerating the baseline in the same commit:
That turns a silent loss into a visible, reviewed decision.
2. No unexpected duplicate names. Two controls sharing a name submit the value twice. Five legitimate radio/checkbox groups are recorded as allowed; anything else fails.
This is the property the Access and Roles roster in stage E depends on — it mirrors 10
require_member_of_*toggles, and those mirrors must carry nonameattribute. This test is what stops that going wrong.Both assertions were verified to actually fail
A test that never fails is worthless, so I checked each one against a deliberately broken template:
enable_conversation_archivingenable_user_feedbackenable_user_feedback x2Both pass again once reverted.
Baseline
451 literal field names, 5 known groups. Jinja-templated names are excluded, since they can't be compared literally.
Also included: status and handoff doc
docs/explanation/features/ADMIN_SETTINGS_IA_REWORK_STATUS.mdThis rework spans several PRs into a staging branch, and the context needed to continue it safely has been living in conversation history rather than the repo. The doc records:
DevelopmentThat last one is easy to forget and would otherwise leave
Development's CI config permanently altered.Verification
admin_settings.html: 33 pre-existing failures before and after, identical setsVersion
0.260.009. No application behaviour changes in this PR — it is a test, a fixture, and a document.