Skip to content

refactor: features own their route registration (P2 seam: mirror + TLS) - #169

Merged
angeloINTJ merged 1 commit into
mainfrom
feat/features-p2-routes
Sep 26, 2026
Merged

angeloINTJ merged 1 commit into
mainfrom
feat/features-p2-routes

Conversation

@angeloINTJ

Copy link
Copy Markdown
Owner

First P2 seam: features own their route registration

The feature-model foundation (#168) proved the six firmware profiles resolve
from the manifest byte-for-byte and put the entanglement watermark in place.
This is the first seam extraction the watermark exists to reward: a feature's
routes move out of the shared web core and into the feature's own translation
unit, and the scoreboard drops.

What moved

WebManager::begin( ) registered every route, including two feature-guarded
groups the core had to know about with an #if:

Route group Was Now
5 panel-mirror routes (/api/screenshot, /api/touch, …) #if SIMUT_DISPLAY_TFT block in WebManager_Core.cpp registerScreenRoutes( ) in WebManager_History.cpp, beside its handlers
POST /api/tls #ifdef SIMUT_WEB_HTTPS block in WebManager_Core.cpp registerTlsRoutes( ) in WebManager_Tls.cpp

Each function is declared unconditionally in WebManager.h and defined
real-or-no-op inside its unit's existing feature guard. begin( ) now calls
both unconditionally — the web core no longer tests SIMUT_DISPLAY_TFT or
SIMUT_WEB_HTTPS to place a route. This is the pattern the rest of the seams
follow.

Entanglement watermark: 283 → 281 sites (SIMUT_DISPLAY_TFT 39→38,
SIMUT_WEB_HTTPS 11→10 — both drops in WebManager_Core.cpp).

The security half

tools/check_authz.py discovered routes only in WebManager_Core.cpp, so
moving a registration out of the core would have made the authorization gate
blind to it. It is retargeted to parse every WebManager*.cpp — strictly
stronger than before, because all real registrations live in the core today and
the ?op= prose that names _server->on( ) in comments does not match the
route regex (it requires a "path", HTTP_x, registration).

Proof the move preserved authorization coverage: check_authz.py --list is
byte-identical before and after — 62 routes, 52 gated, 10 public-by-design, 0
ungated. The retarget was verified as a no-op on the current tree first, then
the move was verified against the retargeted gate, isolating each change.

Verified

  • check_authz --list identical across the retarget and across the move
  • pico_w_release (TFT+HTTPS, both real paths): Flash 95.6%, budget passes
  • pico_w_air (no panel/HTTPS, both no-op paths): Flash 96.1%, budget passes
  • all 7 native suites pass; gen_features --check and check_features in sync
  • docs/AUTHORIZATION.md prose updated to match the multi-file scan
  • Not flashed on hardware — registration reorg, no handler logic changed

Next in the P2 queue

The bigger seams (sensor drivers at 85 sites across the DS18B20/BME280/DHT22
macros, the SIMUT_AIR/SIMUT_CLI_FULL surfaces) follow the same
register-yourself pattern, each as its own PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jq4auDQppGzmAx1gLKn1z3

The web core registered every route in WebManager::begin( ), including the
panel-mirror routes behind #if SIMUT_DISPLAY_TFT and POST /api/tls behind
#ifdef SIMUT_WEB_HTTPS. The first P2 seam of MODELO_DE_RECURSOS.md moves those
two feature-owned route groups out of the shared core and into the feature's
own translation unit:

  - registerScreenRoutes( ) — the 5 mirror routes, in WebManager_History.cpp
    beside their handlers, under the existing #if SIMUT_DISPLAY_TFT.
  - registerTlsRoutes( )    — POST /api/tls, in WebManager_Tls.cpp under the
    file's existing #ifdef SIMUT_WEB_HTTPS.

Each is declared unconditionally in WebManager.h and defined real-or-no-op in
its unit, so begin( ) calls both unconditionally and the core no longer tests
SIMUT_DISPLAY_TFT or SIMUT_WEB_HTTPS to place a route. Entanglement watermark:
283 -> 281 sites (TFT 39->38, WEB_HTTPS 11->10; both drops in WebManager_Core.cpp).

check_authz.py is the security half of this: it discovered routes only in
WebManager_Core.cpp, so moving a registration out of the core would have made
the gate blind to it. Retargeted it to parse every WebManager*.cpp — strictly
stronger, since all real registrations live in the core today (the ?op= prose
that names "_server->on( )" in comments does not match the route regex). Proof
the move preserved authorization coverage: check_authz.py --list is
byte-identical before and after (62 routes, 52 gated, 10 public-by-design, 0
ungated).

Verified:
  - check_authz --list identical across the retarget and across the move
  - pico_w_release (TFT+HTTPS, both real): Flash 95.6%, budget passes
  - pico_w_air (no panel/HTTPS, both no-ops): Flash 96.1%, budget passes
  - all 7 native suites pass; gen_features --check and check_features in sync
  - not flashed on hardware (registration reorg, no handler logic changed)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jq4auDQppGzmAx1gLKn1z3
@github-actions github-actions Bot added documentation Improvements or additions to documentation tools Build tools, scripts, and developer tooling code Firmware source changes (src/, WebUI.h) labels Sep 26, 2026
@angeloINTJ
angeloINTJ merged commit 059907c into main Sep 26, 2026
10 checks passed
@angeloINTJ
angeloINTJ deleted the feat/features-p2-routes branch September 26, 2026 12:25
@angeloINTJ
angeloINTJ restored the feat/features-p2-routes branch September 26, 2026 12:26
@angeloINTJ
angeloINTJ deleted the feat/features-p2-routes branch September 26, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code Firmware source changes (src/, WebUI.h) documentation Improvements or additions to documentation tools Build tools, scripts, and developer tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant