docs(adr): ADR-0041 — the CRS326 runs RouterOS, keeps neo, and serves TLS - #491
Merged
Merged
Conversation
… TLS (#444) #444 asked for a switch that can do TLS. The purchase already happened — a used MikroTik CRS326-24G-2S+RM, 2026-09-13, recorded by #463 — and the issue's own plan says nothing changes until a cabling window. This is the decision half of that plan, written now rather than at the rack. ADR-0018's note said the successor ADR would be written when the switch was racked. That is the wrong time: `neo` carries every VLAN, so the swap is a house-wide outage, and an outage is not when to weigh a dual-boot device's two operating systems or to decide whether a management LAN survives. The note is amended to say so. Nothing else about it changes, and nothing in the estate does either — `neo` is still the MokerLink, still on plain HTTP. What ADR-0041 decides: RouterOS over SwOS, because SwOS serves HTTP only and speaks v1/v2c only, which reproduces the limit the purchase exists to escape on hardware that is capable of better. The name `neo` and `10.7.7.2` are inherited, and the switch LAN stays — for a reason it did not originally have. network.md explains that LAN as a workaround for a UI that would not bind to a tagged interface; that is the MokerLink's limit and it leaves with it. It survives because an untagged point-to-point link to morpheus is the way back in after a bad bridge VLAN-filtering commit, on the one device that carries every VLAN. `www-ssl` serves a leaf from the estate's CA, not the tier's — a switch cannot ask for an ACME renewal, and blackbox already verifies estate-CA leaves by ca_file, so the switch-ui probe can move to https and actually check the certificate. An SNMPv3 authPriv user, v2c off. Port mirroring stays disabled. It was in #444's selection criteria, and ADR-0006 decided the sensor belongs on morpheus with the switch's mirroring off and available on demand; buying a device that can mirror was never a decision to mirror. swap-the-switch.md is the procedure, in three phases, because only the middle one needs the house offline. Two things in it are not in #444's list. The first is a firewall rule: network.md blocks the switch LAN apart from `10.7.7.2:80`, so disabling plain www before widening that pass to 443 leaves a correctly configured switch that Hicks is not allowed to reach — widen, prove, then close 80. The second is that the MokerLink's SNMP community leaked into a session transcript on 2026-08-20 and SECURITY.md records it as deliberately not rotated, because rotating it meant repeating the residual. That reasoning expires with the hardware only if the value does too, so commissioning derives nothing from it. Also: no per-port VLAN map exists in this repository, and the runbook makes capturing one off the MokerLink the first bench step — 26 cables and no map is how the house comes back wrong. And the port census is the one thing here that could still imply a purchase: 26 copper ports replaced by 24 plus two SFP+, so if more than 24 are populated, an SFP+ copper module edits *Everything still to buy* in the same commit. The buy table is unchanged by this commit; #463 already took the switch's row off it. README's ADR count goes 40 to 41 and its runbook count 25 to 26, both required by check_docs.py; the tree comment at line 210 was separately stale at 39 and is corrected. roadmap.md gains a *Decided but not built* entry, which is what an accepted ADR with no work behind it is. #444 and #84 both stay open until the window. Verified: python3 scripts/check_docs.py green at 10 assertions, ./scripts/lint.sh --require-all green. Refs #444 #84 #85 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 17, 2026
Gerrrt
added a commit
that referenced
this pull request
Sep 17, 2026
… counts
`main` is red. Three failures, all from two PRs merging within a minute of each
other without seeing one another:
README.md:95 claims 41 ADRs; the repository has 42
README.md:96 claims 26 runbooks; the repository has 27
ADR-0041 is claimed by 2 files — renumber the one that landed second
#491 gave ADR-0041 to *Run the CRS326 on RouterOS* at 23:27:57Z and #495 gave
the same number to *Terminate the remote path on the lab* at 23:28:52Z. The
ADR-numbering assertion is exactly the check for this; it fired one merge too
late, because each branch was green against a `main` that did not yet hold the
other.
The remote-path ADR landed second, so it becomes **ADR-0042** — which is what
`check_docs.py` asks for by name. Renumbered: the filename, its own H1, eleven
links that targeted it, and thirteen bare `ADR-0041` mentions that meant it.
Every remaining `ADR-0041` in the tree is the CRS326 one, checked individually
rather than by pattern, because the two ADRs shared a number and a
search-and-replace would have renumbered both.
Two of the bare mentions are inside other ADRs' amendment blockquotes (ADR-0011,
ADR-0014). Updating a pointer to a renumbered file is not revising a decision,
so ADR-0001's immutability is not in question — and leaving them would be
leaving a reference to a number that now means something else.
`open-the-remote-path.md`'s pfSense rule descriptions change with it
(`WireGuard peers — ADR-0042`). Safe: the tunnel does not exist, its runbook is
gated on the jumpbox of #436, and `restore-the-firewall.md` still counts the
tripwires as though it were unbuilt.
The two README counts are the arithmetic consequence of the same two merges —
one ADR and two runbooks arrived, and the sentence that counts them did not
move.
Refs #491 #495
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 17, 2026
Merged
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.
What changed
Nothing, to the running lab.
neois still the MokerLink and still on plainHTTP. This adds ADR-0041, which decides how the already-bought CRS326 is
configured, and
swap-the-switch.md, the three-phase procedure for thecabling window. ADR-0018's banner is amended to point at both.
Why
#444 has already moved past the
decision its body asks for: the switch was bought on 2026-09-13 and recorded by
#463, the buy table is down to two rows, and the correction comment narrowed the
justification to one property — the TLS management interface, with #84 riding
along. What is left is a cabling window, and the device is not here (delivery
estimate slipped to 2026-09-23).
ADR-0018's note said the successor ADR would be written when the switch was
racked. That is the wrong time.
neocarries every VLAN, so the swap is ahouse-wide outage, and an outage is not when to weigh a dual-boot device's two
operating systems. This decides the half that cannot be changed later; the
serial, MAC and shipped firmware go to
hardware.mdat the bench.What ADR-0041 decides: RouterOS over SwOS (SwOS is HTTP-only and v1/v2c-only
— it reproduces the limit the purchase exists to escape). The name
neoand10.7.7.2are inherited and the switch LAN stays, for a reason it did notoriginally have:
network.mdexplains that LAN as a workaround for a UI thatwould not bind to a tagged interface, which is the MokerLink's limit and leaves
with it — it survives because an untagged link to
morpheusis the way back inafter a bad bridge VLAN-filtering commit.
www-sslfrom an estate-CA leaf, notthe tier's (a switch cannot ask for an ACME renewal, and blackbox already
verifies estate-CA leaves by
ca_file). SNMPv3 authPriv, v2c off. Mirroringstays disabled per ADR-0006 — buying a device that can mirror was never a
decision to mirror.
Two things the issue's own cutover list does not mention, both in the
runbook:
network.md:251blocks the switch LAN apart from10.7.7.2:80. Disablingplain
wwwbefore widening that pass to443leaves a correctly configuredswitch that Hicks — the workstation running the window — is not allowed to
reach. Widen, prove, then close
80.SECURITY.mdrecords that the MokerLink's SNMP community leaked into asession transcript on 2026-08-20 and was deliberately not rotated, because
rotating it meant repeating the residual. That reasoning expires with the
hardware only if the value does too, so commissioning derives nothing from it.
(Raised by the session working Retire the MokerLink switch's previous SNMP community #84; verified against
SECURITY.mdbeforewriting.)
Also: no per-port VLAN map exists anywhere in this repository, so capturing one
off the MokerLink is the first bench step — 26 cables and no map is how the
house comes back wrong.
Blast radius
None now. The estate runs unchanged until the window. The runbook's Phase 3 is
where
network.md,generator.yaml, the SNMP and blackbox targets andsnmp-verify.shchange, and none of them are touched here — two peer sessionsown #84 and #85 and those files are theirs until then.
One thing that could still imply a purchase, flagged rather than assumed: 26
copper ports are replaced by 24 plus two SFP+. If the port census shows more
than 24 populated, an SFP+ copper module edits Everything still to buy in the
same commit. The buy table is unchanged by this PR — #463 already took the
switch's row off it.
secrets/*.sops.yamlVerification
python3 scripts/check_docs.py— green at 10 assertions. It caughtthe README counts, as it did on ADR-0039 and ADR-0040: 40 ADRs → 41 and
25 runbooks → 26. The tree comment at
README.md:210was separately staleat 39 and is corrected to 41.
./scripts/lint.sh --require-all— all five linters pass.markdownlintis the gate that matters here: ADR-0018's supersede note is folded into
its existing blockquote, because two adjacent blockquotes are MD028.
pass — ADR-0013 is superseded by ADR-0025, which is the current firewall
record.
make validate— via CI, not locally. Validate configs, Lint andSecret scan are all green on this head. Locally it did not finish: a run
was killed by its own 25-minute budget inside
check_dashboard_roundtrip,which boots Grafana, after every prior step passed — a known slow step on
this host under a busy shared docker daemon, and unrelated to a change
that touches no stack, rule, dashboard or compose file.
Refs #444, #84, #85 — none of them close here. #444 and #84 close at the window.
🤖 Generated with Claude Code