refactor(web): move the skin pages into a skin module (BUNYIP-501) #503

Merged
nrupard merged 4 commits from feat/BUNYIP-501-skin-module into main 2026-08-07 20:26:22 +02:00
Owner

B3 of the BUNYIP-459 epic, part 2: relocate the skin content into a skin module, completing the framework / skin separation started by part 1.

What

The per-app marketing / legal / docs / landing pages now live in bunyip-web/src/skin/, separate from the framework (layout scaffolding, ui, web-edge, and the auth / dashboard / admin handlers that B4 will extract into a shared crate). The framework tree no longer holds this app's page copy or docs.

Changes

  • New bunyip-web/src/skin/ module: public.rs (landing + 404), content.rs (pricing, our-story, roadmap, terms, privacy, docs, feedback), and docs/*.md. Moved wholesale with git mv, so the handler code itself is unchanged.
  • handlers/mod.rs drops the content / public declarations; handlers/ now holds only framework handlers (auth, dashboard, admin, health, onboarding, consent).
  • main.rs gains mod skin and re-sources content / public from skin::, so the route table is unchanged. The two cross-module references (skin::content::trial_phrase from skin::public, skin::public::not_found_content from skin::content) and the docs include_str! paths (../docs/ -> docs/, since docs/ moved under skin/) are updated.

Byte-identical

Pure module re-homing: handler code, rendered output, and routes are unchanged, and the 211 bunyip-web tests pass. Only module paths moved.

Scope note

feedback and the per-application app_docs handlers are generic capabilities that happen to live in content.rs; they moved with it rather than being surgically split out. If B4 wants them in the shared framework crate they can be split then; leaving them in the skin for now keeps this change a safe wholesale move. Brand image assets (bunyip-hero.png, mokosh-logo.png) stay physically under assets/ (served at /assets/*), since relocating them would change public URLs; they are conceptually skin-owned and can move when the skin gets its own served asset dir.

Completes B3 (with part 1)

Part 1 (#502) made the framework chrome read the brand from config; this move puts the skin page bodies and docs in their own module. Together they satisfy BUNYIP-501: the framework carries no bunyip marketing copy, and the skin content is a separable unit.

Stacked

On B3 part 1 (#502) -> B2 (#501) -> merged B1. Base = feat/BUNYIP-501-debrand-chrome.

Validation

cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test -p bunyip-web are green.

B3 of the BUNYIP-459 epic, part 2: relocate the skin content into a `skin` module, completing the framework / skin separation started by part 1. ## What The per-app marketing / legal / docs / landing pages now live in `bunyip-web/src/skin/`, separate from the framework (layout scaffolding, ui, web-edge, and the auth / dashboard / admin handlers that B4 will extract into a shared crate). The framework tree no longer holds this app's page copy or docs. ## Changes - New `bunyip-web/src/skin/` module: `public.rs` (landing + 404), `content.rs` (pricing, our-story, roadmap, terms, privacy, docs, feedback), and `docs/*.md`. Moved wholesale with `git mv`, so the handler code itself is unchanged. - `handlers/mod.rs` drops the `content` / `public` declarations; `handlers/` now holds only framework handlers (auth, dashboard, admin, health, onboarding, consent). - `main.rs` gains `mod skin` and re-sources `content` / `public` from `skin::`, so the route table is unchanged. The two cross-module references (`skin::content::trial_phrase` from `skin::public`, `skin::public::not_found_content` from `skin::content`) and the docs `include_str!` paths (`../docs/` -> `docs/`, since `docs/` moved under `skin/`) are updated. ## Byte-identical Pure module re-homing: handler code, rendered output, and routes are unchanged, and the 211 bunyip-web tests pass. Only module paths moved. ## Scope note `feedback` and the per-application `app_docs` handlers are generic capabilities that happen to live in `content.rs`; they moved with it rather than being surgically split out. If B4 wants them in the shared framework crate they can be split then; leaving them in the skin for now keeps this change a safe wholesale move. Brand image assets (`bunyip-hero.png`, `mokosh-logo.png`) stay physically under `assets/` (served at `/assets/*`), since relocating them would change public URLs; they are conceptually skin-owned and can move when the skin gets its own served asset dir. ## Completes B3 (with part 1) Part 1 (#502) made the framework chrome read the brand from config; this move puts the skin page bodies and docs in their own module. Together they satisfy BUNYIP-501: the framework carries no bunyip marketing copy, and the skin content is a separable unit. ## Stacked On B3 part 1 (#502) -> B2 (#501) -> merged B1. Base = `feat/BUNYIP-501-debrand-chrome`. ## Validation `cargo fmt --all --check`, `cargo clippy --workspace --all-targets -- -D warnings`, and `cargo test -p bunyip-web` are green.
B3 part 2: relocate this app's marketing / legal / docs / landing pages into a bunyip-web/src/skin/ module, separate from the framework (layout scaffolding, ui, web-edge, and the auth / dashboard / admin handlers B4 will extract into a shared crate). The framework tree no longer holds this app's page copy or docs.

public.rs (landing + 404), content.rs (pricing, our-story, roadmap, terms, privacy, docs, feedback), and docs/*.md moved wholesale with git mv, so the handler code is unchanged. handlers/mod.rs drops the content / public declarations; main.rs gains mod skin and re-sources content / public from skin::, leaving the route table unchanged. The two cross-module references and the docs include_str! paths (../docs/ -> docs/) are updated.

Pure module re-homing: rendered output and routes are unchanged and the 211 bunyip-web tests pass. feedback and the per-application app_docs handlers moved with content.rs rather than being surgically split; if B4 wants them framework-shared they can move then. Brand image assets stay under assets/ (served at /assets/*) to keep public URLs stable. Completes BUNYIP-501 with part 1 (the config-driven chrome de-brand). Stacked on #502.

#BUNYIP-501

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard changed target branch from feat/BUNYIP-501-debrand-chrome to main 2026-08-07 20:07:18 +02:00
Merge branch 'main' into feat/BUNYIP-501-skin-module
Some checks failed
E2E / PR gate (pull_request) Successful in 43s
Check / fmt + clippy + build + tests (pull_request) Has been cancelled
0d1d6a0393
nrupard scheduled this pull request to auto merge when all checks succeed 2026-08-07 20:07:41 +02:00
B5 of the theme-agnostic web-kit epic. A skin with different third-party integrations extends bunyip-web's Content-Security-Policy without editing security.rs.

Config.csp: CspConfig { connect_src, form_action } is populated from CSP_CONNECT_SRC / CSP_FORM_ACTION (comma-separated) and mirrors dunite-core's CspConfig shape. security.rs::policy() appends the skin's hosts to connect-src and form-action only; the script-src 'self' / default-src / frame-ancestors lockdown (BUNYIP-424) is never extended by config. A new test asserts the skin hosts land in connect-src / form-action and never leak into script-src / default-src / img-src, and another pins that an empty config is byte-identical to the previous policy. .env.example documents the two variables.

bunyip-web is a standalone binary with no dunite-core dependency, so the CspConfig shape is mirrored locally rather than pulling in the dependency and rewriting the bespoke policy builder; B4 (the web-kit crate) is where the web-edge security module unifies with dunite-core's CspConfig. Empty config yields the byte-identical default policy; the 213 bunyip-web tests pass. Stacked on #503.

#BUNYIP-503

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Merge pull request 'feat(web): make the CSP host allow-list a config input (BUNYIP-503)' (#504) from feat/BUNYIP-503-csp-config into feat/BUNYIP-501-skin-module
All checks were successful
E2E / PR gate (pull_request) Successful in 37s
Check / fmt + clippy + build + tests (pull_request) Successful in 9m23s
Create release / Create release from merged PR (pull_request) Has been skipped
00199db8e2
Reviewed-on: #504
nrupard deleted branch feat/BUNYIP-501-skin-module 2026-08-07 20:26:22 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!503
No description provided.