Certificates page: make forcing netboot HTTPS a switch, and give it a way back to derived - #1732
Merged
Merged
Conversation
The netboot transport row rendered its raw http|https domain as a select. Two things were wrong with that, and the second is a bug rather than a look. It did not read as a control. A form-select-sm in the table's narrow first column comes out as a bare `http` chip beside three switches that are obviously interactive, and its title -- "Netboot fetches boot.php over" -- was a dangling phrase the select was there to complete. More seriously, http|https is not the question this row asks. _resolveNetbootProto() DERIVES the transport on every run from the two settings above it, and stops deriving only once BOOT_url_proto_forced is yes. Both real transports set that flag when the installer reads them. So the control offered exactly two values, both of which pinned the server, and none that released it: a server deriving https from a public certificate was pinned by the first interaction and never derived again, whatever its certificate later became. Nothing said so, and the row went on displaying the same word it had before. So the row asks the yes/no it actually means -- "forced to https, or left to derive" -- as a fourth switch beside the three it belongs with, and off posts `auto`, a third member of the domain that is not a transport. The helper turns it into BOOT_url_proto_forced=no and writes nothing else, so the next run derives again. That writes a key absent from PREF_KEYS, which is not a hole in ADR 0036's refusal. The refusal was about FORCING https with neither steering key set -- "not a thing a misclick should reach". `auto` only ever writes `no`, and clearing a force can do nothing but return the value to what derivation already says. Reaching forced=yes still means posting https to a control that says so, and set-preference still refuses BOOT_url_proto_forced as a key. The row now also says what is in effect and why -- "currently https (derived from the public CA setting above)" versus "(forced)" -- because a derived https and a forced https are the same word and a different fact, and the switch cannot render correctly without telling them apart. That needs the flag reported, so status loops over a new REPORT_KEYS. Two lists deliberately: PREF_KEYS stays the write allowlist and the security boundary, REPORT_KEYS is only what the page may see. Forcing plain http is no longer reachable from the page. It is the rare case, it is the direction that breaks netboot rather than repairs it, and installfog.sh --netboot-proto http still does it. The bespoke JS handler goes away with the select -- the switch posts the same flag as the other three, and the page maps that flag to https or auto on the way to the helper. Tests. certificate-table pins all four states separately, because checked-state and displayed-state are different facts that coincide in only one of them; 7 of the 9 fail against the old row, and making the switch read the transport instead of the forced flag fails exactly the derived-https assertion. certificate-management-permission pins both halves of the auto contract and that the page never maps off to http. pki-admin-helper covers the behaviour: auto clears the flag and leaves the transport alone, the flag is refused as a key in either direction, and status reports it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ps28eGTALgieR6TBUSafVg
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.
The row today
It does not read as a control. A
form-select-smin the narrow first columnrenders as a bare
httpchip beside three switches that are obviouslyinteractive, and the title
Netboot fetches boot.php overis a dangling phrasethe select was there to complete.
And
http|httpsis not the question this row asks._resolveNetbootProto()derives the transport on every run from the two settings above it:
Both real transports set
BOOT_url_proto_forced=yeswhen the installerreads them. So the control offered two values, both of which pinned the server,
and none that released it — a one-way door. A server deriving
httpsfrom apublic certificate was pinned by the first interaction and never derived again,
whatever its certificate later became. Nothing said so: the row went on
displaying the same word it displayed before.
The row now
A fourth switch, beside the three it belongs with, asking the yes/no it actually
means: forced to https, or left to derive.
Off posts
auto— a third member of the domain that is not a transport. Thehelper turns it into
BOOT_url_proto_forced=noand writes nothing else, so thenext run derives again.
That writes a key deliberately absent from
PREF_KEYS, and I do not think it isa hole in ADR 0036's refusal. That refusal was about forcing HTTPS with
neither steering key set — "not a thing a misclick should reach."
autoonlyever writes
no, and clearing a force can do nothing but return the value towhat derivation already says. Reaching
forced=yesstill means postinghttpsto a control that says so, and
set-preferencestill refusesBOOT_url_proto_forcedas a key in either direction. This is the judgementcall most worth a second opinion.
The row says what is in effect and why —
(forced)vs(derived from the public CA setting above)vs(derived). A derivedhttpsand a forcedhttpsare the same word and a different fact, and the switch cannot render correctly
without telling them apart. That needs the flag reported, so
statusloops overa new
REPORT_KEYS. Two lists on purpose:PREF_KEYSstays the write allowlistand the security boundary;
REPORT_KEYSis only what the page may see.Forcing plain http leaves the page. Rare case, the direction that breaks
netboot rather than repairs it, and
installfog.sh --netboot-proto httpstilldoes it. The row still renders a CLI-forced http truthfully.
The bespoke JS handler goes away with the select — the switch posts the same
flag as the other three, and the page maps that flag to
https/auto.Not changed, because it is already true and pinned: netboot is excluded from the
HTTP→HTTPS redirect (
vhost-netboot-exclusion13/13).Testing
certificate-tablecertificate-management-permissionvhost-netboot-exclusioninstall-settings-resolutionboolean-encodingAll four states are pinned separately — checked-state and displayed-state
are different facts that coincide in only one of them.
Mutation-tested rather than merely green:
certificate-tableassertions failhttpsassertion failsautofalls through and writes itself as a transporthttpinstead ofautoNot verified locally
phpstan(both passes) did not run — novendor/here. Thetests/passbaselines occurrence counts, and this adds
preg_match/preg_match_allandclosures to two baselined files, so a
count:may need bumping.pki-admin-helper.test.shSKIPs here — it needsunshare/root, so itsnew assertions are CI-verified only. The page-side and source-level contracts
it pairs with do run locally and pass.
looks is not.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Ps28eGTALgieR6TBUSafVg