# Changelog All notable changes to website-impl are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Not versioned until production deployment — see `.ontology/state.ncl` for current `deployment-readiness` state. ## [Unreleased] ### Changed — Server Restructuring & on+re migration (2026-04-06) - **Server restructured** to rustelo template pattern (app.rs, run.rs, shell.rs, resources.rs, theme.rs) — custom auth stack removed - **Auth removed**: JWT, OTP, WebSocket hot-reload, user dashboard, server_fns.rs, database/auth.rs — `auth-system` dimension regressed to `build-time-only` - **Project showcase pages** added: kogral, vapora, rustelo, syntaxis, typedialog, secretumvault, stratumiops, provisioning, ontoref, work_request, services - **Post viewer simplified**: client.rs and html_generator.rs removed, only mod.rs remains - **CSS scripts moved** from `scripts/` to `scripts/build/` subdirectory - **on+re migration**: `state.ncl` — new `build-time-only` state in auth-system, deployment-readiness pre-production description updated, transition blockers updated - **on+re migration**: `core.ncl` — hydration-strategy artifact paths corrected, auth-rbac-impl updated (build-time only), user-dashboard updated (removed, FTL preserved), css-asset-pipeline script paths updated, new `project-showcase-pages` node added - **ADR-001** (website-impl): Server Template Restructuring — auth removal constraints captured ### Added — Architecture Self-Description (2026-03-14) - **on+re protocol** integrated: `.ontology/` + `adrs/` + `reflection/` in place - `.ontology/core.ncl` — knowledge graph as Rustelo Service consumer: axioms (`rustelo-consumer`, `bilingual-content`), tensions (hydration complexity, build-time vs runtime), project nodes (build-time codegen impl, hydration strategy, cache layer, NCL config, custom routing impl, auth RBAC, user dashboard, CSS asset pipeline) - `.ontology/state.ncl` — four tracked dimensions: `deployment-readiness` (development → **pre-production**), `hydration-stability` (stabilized → **zero-mismatch**), `auth-system` (**operational**), `css-pipeline` (**correct**) - `.ontology/gate.ncl` — `hydration-parity` (Low permeability, Challenge protocol), `content-integrity` (Medium, Observe protocol), `rbac-correctness` (Low, Challenge protocol) - `.ontology/manifest.ncl` — Service manifest with EndUser, Developer, Agent consumption modes; `rustelo-browse` operational mode for cross-project framework capability browsing - `reflection/` — backlog, constraints, defaults, qa, schema; modes: `integrity-check`, `sync-ontology`, `validate-content`, `validate-hydration` - `adrs/adr-001-ncl-over-toml.ncl` — NCL (Nickel) over TOML for site configuration - `adrs/adr-002-hydration-strategy.ncl` — SsrTranslator in both SSR+WASM targets; 6 hard/soft constraints including `menu-registry-language-keyed`, `reactive-closure-copy-only`, `spa-content-id-not-slug` - `adrs/adr-003-ws-rbac-hot-reload.ncl` — WebSocket broadcast for RBAC hot-reload without server restart; 3 constraints (`content-module-always-compiled`, `chrono-non-optional`, `server-enforcement-primary`) ### Added — User Dashboard (2026-03-03) - 5-tab authenticated user area: Perfil, Marcadores, Mensajes, Notas, Recursos - DB migrations `005_user_dashboard_{postgres,sqlite}.sql`: `user_messages`, `user_notes`, `user_resources` tables - `database/auth.rs`: `MessageRow`, `NoteRow`, `ResourceRow` + 7 query methods - `server_fns.rs`: 7 server functions (`UserMessage`, `UserNote`, `UserResource`) - `otp_service.rs` + `otp_adapter.rs`: trait + full implementation for all 7 methods - `site/rbac.ncl`: 7 endpoint allow rules for `user` group - `site/i18n/locales/{en,es}/pages/user.ftl`: ~20 new i18n keys per language - `crates/pages/src/user/unified.rs`: 5-tab dashboard rewrite with signal-safety patterns ### Fixed — NavMenu Auth & RBAC (2026-03-03) - `AuthControls` moved inline in `UnifiedNavMenu` (desktop + mobile) — no longer a fixed overlay - `navmenu/unified.rs`: auth strings (`nav-sign-in`, `nav-sign-out`, `nav-dashboard`) computed inside reactive closures via `UnifiedI18n::new` — reactive to language changes - `site/rbac.ncl`: authenticated `user` group allow rules for assets, `track_page_view*`, `server_update_display_name*` - `database/auth.rs`: `parse_sqlite_datetime()` helper handles both RFC3339 and `%Y-%m-%d %H:%M:%S` — fixes OTP login panic on SQLite `datetime('now')` format ### Added — RBAC Hot-Reload via WebSocket (2026-03-01) - `site/rbac.ncl` file-watch triggers in-process server reload of `AUTH_PATTERNS` - New patterns broadcast over WebSocket to all connected WASM clients - WASM receives broadcast and updates reactive signal — UI gates update without page reload - `content` module compiled unconditionally (no feature gate); `chrono` made non-optional ### Fixed — CSS Asset Pipeline (2026-03-05) - `scripts/build-css-bundles.js`: reads from correct source (`site/assets/styles/`, not cache) - `scripts/download-highlight-css.js`: output to `site/public/assets/styles/` (was `public/styles/`) - `scripts/download-highlightjs-copy-css.js`: output path fixed + converted to ES modules - `scripts/copy-css-assets.js`: excludes `.DS_Store`, `.toml`, and `themes/` directory from public sync - `package.json`: `highlightjs-copy:css` added to build pipeline - `site/config/assets.ncl`: all CSS paths corrected from `/styles/` → `/assets/styles/` ### Fixed — Hydration: SPA PostViewer Cold-Cache 404 (2026-02-26) - `item.id ≠ item.slug` for some posts — HTML files are named after `item.id`, not `item.slug` - On cold SPA navigation: `load_content_index` returned `[]` → fallback used `url_slug` as filename → 404 - Fix: `AsyncContentUpdater::resolve_and_fetch_content` fetches `index.json`, matches `item.slug == url_slug`, then uses `item.id` for the file path - `_content_memo` gated to `#[cfg(not(target_arch = "wasm32"))]` — was firing in WASM with wrong language ### Fixed — Hydration: WASM FTL Registry (2026-02-26) - `FTL_REGISTRY` was never populated in WASM — all translations fell through to SSR-embedded data (initial language only) - `crates/client/build.rs`: generates `ftl_registry_fn.rs` with `include_str!` for every `.ftl` file (46 entries for en+es) - `crates/client/src/lib.rs`: calls `populate_wasm_ftl_registry()` at WASM startup — populates registry before any component renders - Language switching now works correctly in WASM: `get_parsed_ftl_for_language("en")` finds all `en_*` keys ### Fixed — Hydration: Page Cache Empty HashMap (2026-02-26) - All 15 `*Client` cache components passed `HashMap::new()` as `lang_content` — caused `HtmlContent` empty `inner_html` → tachys `` placeholder → cursor desync → hydration panic - `target/rustelo-cache/pages/page_*.rs` `*Client` components: replaced `HashMap::new()` with `SsrTranslator` + `build_page_content_patterns` - `build_page_generator.rs` template updated — future regenerations produce structurally identical code for both targets ### Fixed — Hydration: Menu Registry Key Mismatch (2026-02-26) - `MENU_REGISTRY` keyed `"main"` in WASM init; `get_menu(lang)` looks up by `"en"`/`"es"` → 0 items in WASM vs 6 in server - `crates/server/build.rs` + `crates/client/build.rs`: now insert per-language keys (`"en"`, `"es"`) from `config.ncl` routes - `navmenu/unified.rs`: `lang_signal.get_untracked()` in SSR to suppress tracking-context warning ### Added — Configuration-Driven Routing (2026-02-25) - `routing.rs` fully rewritten: uses `ROUTE_TABLE` (BTreeMap from NCL config) — no hardcoded paths - `build.rs`: reads `site/config/routes/*.ncl`, generates `route_table.rs` + `RouteComponent` enum - `lib.rs`: `#![recursion_limit = "512"]` added for complex generated types ### Added — NCL Configuration (2026-02-09) - Route configuration migrated from `*.toml` to `site/config/routes/*.ncl` - RBAC rules in `site/rbac.ncl` with typed contracts - Asset configuration in `site/config/assets.ncl` - Reusable schemas in `site/schemas/` for content, menus, footer, themes - Bilingual menus in single NCL file (eliminated en.toml/es.toml duplication)