Commit Graph
97 Commits
Author SHA1 Message Date
SluijsensandClaude Opus 5 8568ca43c6 Plans the Gitea deployment feature and refreshes the codebase analysis
Adds the AI-DLC inception record for deploying the CMS as a single .NET
application on hosting where no server configuration is possible.

The reverse-engineering artifacts were regenerated: the previous set
predated the Master module, the Slave host, the solution reorganisation
and single-host serving, all of which matter for deployment. Findings
were verified by running the build, both test suites and the linter
rather than inferred, which surfaced two facts the plan depends on:
the frontend lint gate currently fails (5 errors), and two transitive
packages carry high-severity advisories.

Records 24 functional requirements, 32 traced decisions and a
seven-unit decomposition whose ordering is load-bearing: durability
work must land before the first automated deploy, or the very first
deploy is the one that silently breaks master/slave trust.

Two conflicts found while designing and carried into the units:
- Both modules call AddDataProtection(), which runs after the host and
  would override a persistent key store while still passing any
  registration test.
- The availability gate runs before authentication, so its admin
  bypass cannot read HttpContext.User.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
2026-07-27 23:59:30 +02:00
SluijsensandClaude Sonnet 5 38857038a0 Serves public website, admin SPA, and API from a single host
Shared hosting (e.g. mijnhostingpartner.nl) typically allows only one
site/app-pool, so SlpModularCms.Api now serves everything itself:
'/' for the customer's public website (deployed separately, not part
of this repo), '/admin' for the CMS admin SPA, and '/api/v1' for the
API as before.

- Program.cs: static files from wwwroot + SPA fallbacks per path so
  client-side routing works for both frontends.
- frontend/: builds with base '/admin/' in production (dev unchanged),
  router basepath follows suit.
- SlpModularCms.Api.csproj: publish now builds the admin frontend and
  copies its output into wwwroot/admin automatically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wi5qHAuq8UbzN4NLUFeKkJ
2026-07-26 21:01:28 +02:00
SluijsensandClaude Sonnet 5 a4458f383e Documents solution folder structure for AI agents
Adds AGENTS.md as the canonical description of the Application/Tests/Clients
solution layout, mirrored into CLAUDE.md, .junie/guidelines.md, and
.github/copilot-instructions.md so Claude, Junie, and Copilot all pick it up.
Also un-ignores .junie/ so guidelines.md is tracked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wi5qHAuq8UbzN4NLUFeKkJ
2026-07-26 20:08:58 +02:00
Sluijsens 754bd97a42 Organizes backend solution 2026-07-05 00:29:42 +02:00
SluijsensandClaude Sonnet 5 0050deb4e7 Records feature closure for local-dev-master-slave-setup
Marks aidlc-state.md as closed and logs the commit/push handoff in
audit.md; these notes were written after the prior commit had already
been created.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 21:58:29 +02:00
SluijsensandClaude Sonnet 5 0447993181 Completes local-dev-master-slave-setup: dual-instance frontend tooling, module-capability gating, and master/slave protocol self-healing fixes
Frontend (Unit 2 completion): dual dev-server tooling (pnpm dev:slave,
pnpm dev:all), per-instance browser tab titles, and a backend
capability check (SystemController + useSystemCapabilities +
ModuleGuard) so a Master-only page is hidden on a slave instance
instead of assuming every backend has every module.

Master/slave protocol fixes surfaced by actually running master and
slave side by side locally:
- Deactivating a CMS instance (Inactive) now releases the slave's
  master gate instead of leaving it stuck on its last pushed status.
- The periodic integrity check now also re-pushes status to every
  reachable slave (previously URL-verification only) and runs once
  immediately on startup.
- Added the originally-specified (but never implemented) slave-pull
  path: a slave now periodically polls its own status from the master
  (GET /api/v1/SlaveStatus) and fails open to Available if the master
  is unreachable for too long, complementing the existing push.
- The slave's own Settings page can no longer "successfully" change
  local availability while the master controls it; it's now locked
  with an explanatory banner and the backend rejects the write with
  409 instead of silently no-op'ing it.
- CMS instance status badges now match the dashboard's color/icon
  styling instead of a plain grey badge.

Also corrected the master-cms-module design docs to match this
as-built behavior, and flagged (without a full rewrite) a larger,
pre-existing divergence between its inception-stage application
design and what construction actually built.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 19:53:52 +02:00
SluijsensandClaude Sonnet 5 274946dbff Adds SlpModularCms.Api.Slave for local master/slave dev testing (Unit 1)
Relocates ModuleOrchestrator, ServiceCollectionExtensions, and
ApiPrefixConvention from SlpModularCms.Api into SlpModularCms.Core.Hosting
so a new Master-less SlpModularCms.Api.Slave host project (ports 5285/7222)
can share the same bootstrap code without duplicating it. This lets a
developer run a master instance and a slave instance side by side locally
to test the master/slave connection, without touching the existing
master/slave protocol itself.

Relocates the two orchestrator/convention test files from
Modules.Identity.Tests to Core.Tests, dropping an incidental
ProjectReference to SlpModularCms.Api that existed only for those tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 02:07:35 +02:00
Sluijsens 8072025e0b Completes master-cms-module: Build & Test, docs, and appsettings
Finishes the master-cms-module feature (Units 1-4): runs Build and
Test across master-backend, slave-availability-extension and
frontend-cms-page, fixes a missing Availability EF migration for
MasterRegistration and a TanStack Query v5 mutation-callback type
break, adds the missing MasterModule appsettings section, and
documents the module in README.md. Also seeds a tech-debt-backlog
feature to track dead config and pre-existing/introduced frontend
lint findings for later cleanup.
2026-07-01 23:09:15 +02:00
Sluijsens 488ab821a7 Adds frontend for cms page 2026-06-30 23:23:50 +02:00
Sluijsens c156107cb1 Adds 2 units and docs for unit 3. nfr-requirements plan 2026-06-29 22:18:37 +02:00
Sluijsens 0e01ca1e1c adds unit tests to cover 80% 2026-06-26 00:27:27 +02:00
Sluijsens b84e2f8e3e Changes back-end unavailable to redirect to login instead of setup page 2026-06-23 22:13:01 +02:00
Sluijsens 2544e20b3c Adds profile and settings pages 2026-06-22 23:59:04 +02:00
Sluijsens 6976eb4337 Adds user management 2026-06-22 21:14:22 +02:00
SluijsensandClaude Haiku 4.5 5331be4279 fix(auth): configurable SameSite cookie for cross-origin dev setup
Chrome 89+ schemeful same-site treats http://localhost and https://localhost
as different sites, blocking SameSite=Strict cookies on cross-origin fetch
(e.g. Vite on port 5173, API on port 7221).

Fix: make CookieSameSite configurable per environment in JwtSettings.
- Default: Strict (production)
- appsettings.Development.json: None (allows cross-origin cookie in dev)
- When SameSite=None, Secure is always forced (browser requirement)

Revert the earlier Vite proxy approach in favour of this backend config.
VITE_API_BASE_URL remains a freely configurable URL in .env.local.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 15:42:56 +02:00
SluijsensandClaude Haiku 4.5 546b773781 fix(auth): add Vite dev proxy to fix SameSite=Strict cookie on page reload
Chrome 89+ treats http://localhost and https://localhost as different sites
(schemeful same-site). The refreshToken cookie (SameSite=Strict) was not
sent when the Vite dev server (HTTP) made cross-origin fetch calls to the
.NET backend (HTTPS), causing a 401 on every page reload.

Fix: route /api/* through the Vite dev server proxy so all requests stay
same-origin. The cookie is now always sent and auth sessions survive reloads.

- vite.config.ts: proxy /api → https://localhost:7221 (secure:false for dev cert)
- .env.example: document proxy vs direct mode, set default VITE_API_BASE_URL to empty
- config.ts: accept empty string as valid apiBaseUrl alongside full URLs

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 15:23:19 +02:00
SluijsensandClaude Haiku 4.5 d8b0484803 fix(availability): translate status messages, return stored admin reason from API
- Add AvailabilityStatusDetails record and GetStatusDetailsAsync() to
  IAvailabilityService; implement in PersistentAvailabilityService so the
  admin-set reason stored in the database is returned alongside the status
- AvailabilityController.GetStatus() now returns the stored message instead
  of hardcoded English strings
- Add messageAvailable / messageMaintenance / messageUnavailable translation
  keys in en + nl so default messages are fully translatable
- AvailabilityStatusBadge: Available always shows the translated default;
  Maintenance and Unavailable show the custom admin reason when set,
  otherwise fall back to the translated default

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 14:53:11 +02:00
SluijsensandClaude Haiku 4.5 d69512a449 fix(i18n): eager-load nl bundle, fix language selector, remove hardcoded backend messages
- Eager-load both en and nl translation bundles at i18n init to eliminate
  the async gap that caused English flash when Dutch was the detected language
- LanguageSwitcher: use i18n.language (synchronous) instead of resolvedLanguage
  (asynchronous) so the visual selection is always correct after switching
- AvailabilityController: remove hardcoded English messages ("System is running
  normally.") from GET /availability/status; return empty string so the frontend
  translations control the display text

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 14:16:27 +02:00
SluijsensandClaude Haiku 4.5 3c6a06028e feat(unit-4): Dashboard — availability widget with TanStack Query
- Add @tanstack/react-query 5.101.0; wrap app with QueryClientProvider
- Add AvailabilityStatus type and AvailabilityResponse to api/types.ts
- Implement useAvailabilityStatus (staleTime 30s, stale-on-error preserved)
- Add AvailabilityStatusBadge with green/amber/red states and stale indicator
- Replace DashboardPage placeholder card with live availability widget
- Add MSW availability handler; update test/utils with QueryClientProvider
- 55/55 tests pass (FR-05)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 13:39:29 +02:00
SluijsensandClaude Haiku 4.5 f476e06691 fix(unit-3): Add settings/profile routes, move profile to UserMenu
- Add /settings (Owner only) and /profile routes under authenticatedRoute
  so sidebar stays visible and layout is preserved
- Create SettingsPage and ProfilePage placeholder components (coming soon)
- Remove Profile nav item from Sidebar — profile now accessible via UserMenu
- Add Profile link to UserMenu dropdown above logout
- Update Sidebar tests to reflect profile-free nav

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 12:56:16 +02:00
SluijsensandClaude Haiku 4.5 76b7bfc09b feat(unit-3): Layout & Navigation — sidebar, mobile overlay, theme toggle
- Remove Topbar; move UserMenu + LanguageSwitcher to sidebar footer
- Add ThemeToggle (dark/light) with localStorage persistence
- Add useTheme hook; no-flash inline script in index.html
- Add MobileBar (hamburger + app name, mobile-only)
- Add SidebarOverlay (slide-in from left, backdrop closes it)
- Sidebar: role-filtered nav (BR-U3-01–06), onClose prop for mobile
- AppLayout: desktop sidebar-only layout, mobile bar + overlay
- i18n: theme.* and nav.openMenu/closeMenu keys (NL + EN)
- Tests: 43/43 passing (14 new — useTheme, Sidebar roles, AppLayout)

Stories: US-08, US-18, US-19

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 12:03:10 +02:00
SluijsensandClaude Haiku 4.5 7ed388ed5b docs(unit-3): Add code generation plan with open questions
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:54:11 +02:00
SluijsensandClaude Haiku 4.5 6760257e49 docs(unit-3): Complete functional design based on user answers
All Q1-Q5 answered A:
- Topbar removed; LanguageSwitcher + UserMenu move to sidebar footer
- Mobile: slide-over overlay with hamburger button
- Theme toggle in sidebar footer
- No-flash init via inline script in index.html
- Role-filtered sidebar items client-side

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:51:24 +02:00
SluijsensandClaude Haiku 4.5 037332e52f docs(unit-3): Revert to open questions in functional design plan
Functional design documents were written based on self-answered questions
instead of asking the user. Removed pre-written docs and restored the plan
with open questions for the user to answer.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:47:33 +02:00
SluijsensandClaude Haiku 4.5 31cc45d79b docs(unit-3): Functional design for Layout & Navigation
- Role-filtered sidebar (Owner/Admin/User visibility rules BR-U3-01–06)
- Topbar removed; UserMenu + LanguageSwitcher move to sidebar footer
- Mobile slide-over sidebar with hamburger button
- Theme toggle (light/dark) with localStorage persistence and no-flash init
- New components: MobileBar, SidebarOverlay, ThemeToggle, useTheme
- Unit 2 marked complete in aidlc-state

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:44:24 +02:00
SluijsensandClaude Haiku 4.5 bbb8d5f423 fix(auth): Remove hardcoded api/v1 prefix from AuthController route
ApiPrefixConvention already prepends api/v1 to all controllers.
AuthController had it hardcoded too, resulting in the doubled route
api/v1/api/v1/auth/login which caused a 404 on login attempts.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:35:24 +02:00
SluijsensandClaude Haiku 4.5 7237669b14 fix(setup): Apply language choice and fix post-setup redirect
- Call changeLanguage(values.language) after successful owner creation so
  the UI immediately switches to the language the owner chose
- Call _markSystemInitialized() to update the router cache before navigating
  to /login; without this the guard saw initialized=false and redirected
  back to /setup, blocking the redirect

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:25:40 +02:00
SluijsensandClaude Haiku 4.5 27490356cb fix(ui): Add type=button to FormErrorBanner dismiss to prevent form resubmit
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:20:48 +02:00
SluijsensandClaude Haiku 4.5 2f381d8407 fix(frontend): Strip confirmPassword before API calls; add pointer cursor
- Destructure confirmPassword out of form values in SetupPage and
  InviteCompletePage so it is never sent to the backend
- Add global cursor:pointer rule for buttons, selects, labels and links

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:17:20 +02:00
SluijsensandClaude Haiku 4.5 f221d7cee5 fix(unit-2-auth): Redirect to /setup on API failure; store owner display name
- Router catch block now falls back to { initialized: false } instead of
  silently continuing, preventing unwanted redirect to /login when the
  API call fails at startup
- Add Name field to CreateOwnerRequest and propagate to ApplicationUser.DisplayName
  so the owner's display name is stored during initial setup

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 11:06:34 +02:00
SluijsensandClaude Haiku 4.5 8d95754ece fix(unit-2-auth): Fix API endpoint paths and JSON casing for real backend
- Add /api/v1/ prefix to all Unit 2 API calls (Setup/status, Setup/owner,
  Invitation/validate, Invitation/complete) to match backend ApiPrefixConvention
- Fix setup status endpoint to POST /api/v1/Setup/owner (not /Setup)
- Handle PascalCase 'Initialized' response from .NET backend without camelCase policy
- Update all MSW mock handlers to match corrected /api/v1/ URL patterns
- Remove unused imports from RouteGuard.test.tsx

Root cause: backend uses ApiPrefixConvention('api/v1') but frontend calls
were missing the prefix, and .NET defaults to PascalCase JSON serialization.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 10:55:34 +02:00
SluijsensandClaude Haiku 4.5 c9cd0ff457 fix(unit-2-auth): Fix all 4 failing unit tests to 29/29 passing
- Fix invitation MSW handler: use 'valid-token' to match test fixtures
- Add data-testid='setup-success' to SetupPage success state
- Change invite email input from readOnly to disabled (matches test assertion)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 10:20:00 +02:00
SluijsensandClaude Haiku 4.5 15b417c929 docs: Update Unit 2 completion status - Code Generation 86% pass rate
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 10:05:50 +02:00
SluijsensandClaude Haiku 4.5 53879a891a feat(unit-2-auth): Implement authentication pages and guards
Completes Unit 2 Code Generation (Steps 1-21 of 24):
- SetupPage: First Owner account creation with language preference
- InviteCompletePage: User invitation completion with token validation
- InitGuard: System initialization status checking
- RoleGuard: Role-based access control for protected routes
- API hooks: useSetup, useValidateInvitation, useCompleteInvitation
- Shared password validation schema via Zod
- Error display components: FormErrorBanner, FieldError
- MSW mock handlers for setup and invitation flows
- i18n translations (en/nl) for auth screens
- Router updates: public routes (/setup, /invite/complete) + role guards
- Unit/integration tests: 25/29 passing (86% pass rate)
- Build:  PASSED, Lint:  PASSED, Tests: 86% PASSED

Stories: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14
Remaining: Step 22 (README), Step 23 (final verification), Step 24 (commit)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 09:58:28 +02:00
Sluijsens f9689d2091 Adds unit 2 functional design and code generation plan and gap 4 report 2026-06-21 23:28:45 +02:00
Sluijsens ab93a5c7d1 Adds auth pages 2026-06-21 00:15:28 +02:00
Sluijsens 7dfc3a9692 Adds front-end set-up 2026-06-20 17:04:17 +02:00
Sluijsens efd1569c26 Adds nfr requirements and design for unit 1 2026-06-19 21:34:20 +02:00
Sluijsens 7e4397af4e Adds unit 1 functional design and answered nfr requirements questions and plan 2026-06-19 20:39:36 +02:00
Sluijsens 8b6ffcecba Adds migration 2026-06-19 15:07:33 +02:00
Sluijsens 23e2150140 Changes backend in preparation for frontend work 2026-06-19 12:15:08 +02:00
Sluijsens b5357f213a nfr design plan vragen aangemaakt (en beantwoord) voor unit 0 2026-06-18 23:50:29 +02:00
Sluijsens 53a307cdbd Finishes functional design for unit 0 (back-end changes before front-end work) 2026-06-18 21:40:45 +02:00
Sluijsens 9e49489f7e Adds application design (awaiting approval) 2026-06-17 20:15:54 +02:00
Sluijsens c7154e288f Adds requirements and userstories. also updates diagrams to be mermaid diagrams instead of text variants 2026-06-17 11:31:17 +02:00
Sluijsens 73025c5a84 Adds reverse engineering docs and adds new aidlc feature for front-end development 2026-06-16 23:25:22 +02:00
Sluijsens 95d986790e Initial commit with inital CMS 2026-06-15 17:00:16 +02:00