Files
SluijsensandClaude Sonnet 5 fa389e42ee
Continuous Integration / config (pull_request) Successful in 11s
Continuous Integration / changes (pull_request) Successful in 21s
Continuous Integration / backend-build (pull_request) Successful in 6m10s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m59s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m27s
Continuous Integration / backend-test (pull_request) Failing after 7m48s
Continuous Integration / frontend-build (pull_request) Successful in 2m5s
Continuous Integration / frontend-test (pull_request) Successful in 4m24s
Continuous Integration / frontend-lint (pull_request) Successful in 2m0s
Continuous Integration / publish-test (pull_request) Skipped
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-test (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Adds SlpModularCms.Api.SlpSoftware and extracts shared CmsHost composition
Unit 1 of the slpsoftware-api feature (FR-1/FR-2/FR-3): a new Client project
in the Clients solution folder, intended to eventually become the deployed
API for test.slpsoftware.nl/slpsoftware.nl, hosting the same four modules as
SlpModularCms.Api plus a future Offerings module.

- Extracts SlpModularCms.Api/Program.cs's hosting-pipeline composition into
  SlpModularCms.Core.Hosting.CmsHost (ConfigureServices/ConfigurePipeline),
  shared by both Client projects so they cannot drift apart
- Moves StaticContentExtensions.cs + WebsitePlaceholder.html from Api into
  Core, since CmsHost cannot live in Api but Core cannot depend on Api
- Adds SlpModularCms.Api.SlpSoftware with its own isolated local dev database
  and dev ports (5286/7223, distinct from Api's and Api.Slave's)
- Adds SlpModularCms.Api.Tests with WebApplicationFactory-based pipeline
  regression tests (security headers, health check, SPA fallback, rate
  limiting), scoped to Api per NFR Design
- Adds a frontend dev:slpsoftware pnpm script mirroring dev:slave
- Fixes GlobalExceptionHandler logging routine 401s (e.g. an expired/missing
  refresh token) as unhandled errors -- pre-existing, unrelated to this
  feature's own scope, found while testing the new instance

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWyStNL2ZsjrS7FLd7xvvN
2026-08-02 01:28:39 +02:00

18 KiB

Execution Plan — SlpSoftware Production API

Detailed Analysis Summary

Transformation Scope (Brownfield)

  • Transformation Type: Architectural addition, not a rewrite — a new deployable Client project is added alongside the existing one, a piece of existing hosting logic is extracted into a shared location, and one new module is added. No existing deployment model changes (still a single self-hosted ASP.NET Core process per environment).
  • Primary Changes: (1) Extract SlpModularCms.Api/Program.cs's composed hosting pipeline into SlpModularCms.Core (CmsHost.Configure(...)); (2) new SlpModularCms.Api.SlpSoftware Client project consuming that shared method; (3) new SlpModularCms.Modules.Offerings module (entity, DbContext, public endpoint, admin CRUD); (4) Operations-phase CI/CD cutover of the existing pipeline from Api to Api.SlpSoftware.
  • Related Components: SlpModularCms.Core (extraction target + hosts the Offering-adjacent shared conventions), SlpModularCms.Api (must keep working identically after the extraction — it is not itself changing behavior), the existing Gitea Actions pipeline (gitea-deployment-workflow feature's artifacts).

Change Impact Assessment

  • User-facing changes: Yes — new admin CRUD screens for the CMS Administrator persona, and new dynamic (CMS-managed) content on the live website for the Site Visitor persona (requirements.md FR-6, FR-7; stories.md US-01..US-12).
  • Structural changes: Yes — first-ever project in the Clients solution folder; new shared hosting-composition method in Core; new module following the existing IModule pattern.
  • Data model changes: Yes — new Offering entity + OfferingsDbContext (FR-5), isolated per the existing per-module migration pattern.
  • API changes: Yes — new public GET /api/v1/offerings (FR-6) and new authenticated admin endpoints (FR-7).
  • NFR impact: Yes — Security Baseline extension is enabled and blocking (D-11); the hosting-pipeline extraction (FR-3) must preserve Api's existing security headers/rate limiting/Sentry/Data Protection behavior exactly, so it doesn't regress the already-hardened dev host while building the new one on the same foundation.

Component Relationships (Brownfield)

graph TD
    core["SlpModularCms.Core<br/>(hosting composition, Identity, Availability entities)"]
    api["SlpModularCms.Api<br/>(existing dev host)"]
    apiSlp["SlpModularCms.Api.SlpSoftware<br/>(new Client, eventual prod host)"]
    offerings["SlpModularCms.Modules.Offerings<br/>(new module)"]
    identity["SlpModularCms.Modules.Identity"]
    availability["SlpModularCms.Modules.Availability"]
    master["SlpModularCms.Modules.Master"]
    pipeline["Gitea Actions Pipeline<br/>(owned by gitea-deployment-workflow)"]

    core -->|"CmsHost.Configure(...)<br/>consumed by both"| api
    core -->|"CmsHost.Configure(...)"| apiSlp
    apiSlp -->|"hosts"| identity
    apiSlp -->|"hosts"| availability
    apiSlp -->|"hosts"| master
    apiSlp -->|"hosts"| offerings
    api -->|"hosts (unchanged)"| identity
    api -->|"hosts (unchanged)"| availability
    api -->|"hosts (unchanged)"| master
    pipeline -.->|"retargeted (D-15 cutover)<br/>Operations phase"| apiSlp

    classDef core fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000;
    classDef existing fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000;
    classDef new fill:#f6e05e,stroke:#c05621,stroke-width:1px,color:#000;
    classDef external fill:#d6bcfa,stroke:#553c9a,stroke-width:1px,color:#000;

    class core core;
    class api,identity,availability,master existing;
    class apiSlp,offerings new;
    class pipeline external;

Text alternative: Core provides the shared CmsHost.Configure method to both the existing Api (unchanged behavior) and the new Api.SlpSoftware (blue = shared foundation, green = existing/unchanged components, yellow = new components, purple = the externally-owned CI/CD pipeline that gets retargeted in the Operations phase).

  • Primary Component: SlpModularCms.Modules.Offerings (new) and SlpModularCms.Api.SlpSoftware (new)
  • Infrastructure Components: .gitea/workflows/continuous_integration.yaml, .gitea/workflows/deploy-scp.yaml, operations/deployment/deployment-instructions.md (all owned by gitea-deployment-workflow; extended, not duplicated, per D-7/D-15)
  • Shared Components: SlpModularCms.Core (new CmsHost.Configure(...)), SlpModularCms.Modules.Identity, SlpModularCms.Modules.Availability, SlpModularCms.Modules.Master (all hosted, unchanged)
  • Dependent Components: SlpModularCms.Api — does not change behavior, but depends on the FR-3 extraction being behavior-preserving
  • Supporting Components: Existing Sentry-based logging/alerting, existing HierarchicalRoleHandler/AdminOnly policy
Related Component Change Type Change Reason Change Priority
SlpModularCms.Core Minor (additive extraction) FR-3 shared hosting composition Critical (blocks both Client projects)
SlpModularCms.Api Configuration-only (calls the new shared method instead of inline code) FR-3 Critical (regression risk if behavior changes)
SlpModularCms.Api.SlpSoftware Major (new project) FR-1, FR-2 Critical
SlpModularCms.Modules.Offerings (+ Tests) Major (new module) FR-4, FR-5 Critical
Gitea Actions pipeline Minor (retarget existing jobs) FR-9, D-15 Important (Operations phase only, not blocking Construction)

Risk Assessment

  • Risk Level: Medium — multiple components change, but each is independently testable (the Core extraction can be verified against Api's existing test suite before Api.SlpSoftware is even built on top of it), and the highest-risk step (the CI/CD cutover, D-15) is isolated to the Operations phase, coordinated with the feature that already owns that pipeline rather than a fresh, unreviewed change.
  • Rollback Complexity: Moderate — the Core extraction is a straightforward revert if Api's behavior regresses (git revert, Api.SlpSoftware didn't exist to depend on it yet at that point in the sequence). The pipeline cutover (Operations) is a config change to Gitea Actions YAML, revertible the same way.
  • Testing Complexity: Moderate — needs before/after regression coverage on Api for the extraction (NFR impact on security headers/rate limiting/Sentry/Data Protection continuity), plus new unit/integration tests for the Offerings module.

Module Update Strategy

  • Update Approach: Sequential where dependencies require it, then parallel-capable.
    1. Foundation first: Extract CmsHost.Configure(...) into Core and repoint SlpModularCms.Api/Program.cs at it, verifying Api's existing behavior and test suite are unaffected before building anything new on top of the shared method.
    2. Then, in parallel: create SlpModularCms.Api.SlpSoftware (consuming the now-shared method + existing modules) and build out SlpModularCms.Modules.Offerings — these two do not depend on each other's internals, only on the foundation from step 1 and on Api.SlpSoftware existing as a host by the time Offerings needs to be wired in.
    3. Operations last: CI/CD cutover (D-15) only after Construction (Code Generation + Build and Test) has proven both the extraction and the new module.
  • Critical Path: The Core extraction (step 1) — both the new Client project and the continued correctness of the existing dev host depend on it.
  • Coordination Points: The shared CmsHost.Configure(...) signature (must accommodate Api's and Api.SlpSoftware's differing module lists); the CI/CD pipeline hand-off with gitea-deployment-workflow (extend existing jobs, don't fork them).
  • Testing Checkpoints: (a) After the Core extraction — full existing Api test suite + a manual/automated smoke check that Api still serves /admin, static content, health checks, and security headers identically. (b) After Offerings module code generation — its own unit/integration tests (NFR-2). (c) After both units — full Build and Test phase covering Api.SlpSoftware end-to-end. (d) Before the Operations cutover — confirm Api.SlpSoftware has been running successfully (e.g. against test.slpsoftware.nl) prior to repointing production.

Exact unit boundaries and naming are finalized in the Units Generation stage (next after Application Design); this section states the intended dependency order that Units Generation should respect, not the final unit list.


Workflow Visualization

flowchart TD
    Start(["User Request"])

    subgraph INCEPTION["🔵 INCEPTION PHASE"]
        WD["Workspace Detection<br/><b>COMPLETED</b>"]
        RE["Reverse Engineering<br/><b>COMPLETED (reused)</b>"]
        RA["Requirements Analysis<br/><b>COMPLETED</b>"]
        US["User Stories<br/><b>COMPLETED</b>"]
        WP["Workflow Planning<br/><b>COMPLETED</b>"]
        AD["Application Design<br/><b>EXECUTE</b>"]
        UP["Units Planning<br/><b>EXECUTE</b>"]
        UG["Units Generation<br/><b>EXECUTE</b>"]
    end

    subgraph CONSTRUCTION["🟢 CONSTRUCTION PHASE"]
        FD["Functional Design (per unit)<br/><b>EXECUTE</b>"]
        NFRA["NFR Requirements (per unit)<br/><b>EXECUTE</b>"]
        NFRD["NFR Design (per unit)<br/><b>EXECUTE</b>"]
        ID["Infrastructure Design (per unit)<br/><b>EXECUTE</b>"]
        CG["Code Generation<br/>(Planning + Generation)<br/><b>EXECUTE</b>"]
        BT["Build and Test<br/><b>EXECUTE</b>"]
    end

    subgraph OPERATIONS["🟡 OPERATIONS PHASE"]
        DS["Deployment Setup<br/><b>EXECUTE</b>"]
        MS["Monitoring Setup<br/><b>EXECUTE</b>"]
        PRV["Production Readiness Validation<br/><b>EXECUTE</b>"]
    end

    Start --> WD --> RE --> RA --> US --> WP --> AD --> UP --> UG --> FD --> NFRA --> NFRD --> ID --> CG --> BT --> DS --> MS --> PRV --> End(["Complete"])

    style WD fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style RE fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style RA fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style US fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style WP fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style AD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style UP fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style UG fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style FD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style NFRA fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style NFRD fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style ID fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style CG fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style BT fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style DS fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style MS fill:#FFA726,stroke:#E65100,stroke-width:3px,stroke-dasharray: 5 5,color:#000
    style PRV fill:#4CAF50,stroke:#1B5E20,stroke-width:3px,color:#fff
    style Start fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000
    style End fill:#CE93D8,stroke:#6A1B9A,stroke-width:3px,color:#000

    style INCEPTION fill:#BBDEFB,color:#000
    style CONSTRUCTION fill:#C8E6C9,color:#000
    style OPERATIONS fill:#FFF59D,color:#000

    linkStyle default stroke:#333,stroke-width:2px

Text alternative: all Inception stages up to and including Workflow Planning are completed (solid green). Application Design, Units Planning, Units Generation, and all four per-unit Construction design stages (Functional Design, NFR Requirements, NFR Design, Infrastructure Design) are planned to execute (dashed orange). Code Generation and Build and Test always execute (solid green). In Operations, Deployment Setup and Monitoring Setup are planned to execute (dashed orange, each asks its own inclusion question when reached), and Production Readiness Validation always runs once the phase is reached (solid green).


Phases to Execute

🔵 INCEPTION PHASE

  • Workspace Detection (COMPLETED)
  • Reverse Engineering (COMPLETED — reused existing _shared/reverse-engineering/ artifacts, no rerun)
  • Requirements Analysis (COMPLETED)
  • User Stories (COMPLETED)
  • Workflow Planning / Execution Plan (COMPLETED — this document)
  • Application Design — EXECUTE
    • Rationale: New components are introduced (Offering entity, OfferingsDbContext, admin CRUD service layer, the shared CmsHost.Configure(...) method) whose methods, business rules (featured exclusivity, reorder persistence), and dependencies need definition before units can be planned.
  • Units Planning — EXECUTE
    • Rationale: Multiple modules/projects are involved (Core extraction, new Client project, new module) with a real dependency order (Module Update Strategy above) — this needs explicit unit boundaries, not an implicit single unit.
  • Units Generation — EXECUTE
    • Rationale: Same as Units Planning — this is a multi-unit change, not a single simple unit.

🟢 CONSTRUCTION PHASE

(Assessed per unit once Units Generation defines them; overall expectation below.)

  • Functional Design — EXECUTE (primarily for the Offerings unit: new data model + business rules; likely minimal/skippable for a pure hosting-extraction unit — confirmed per-unit)
    • Rationale: New data model (Offering) and non-trivial business rules (exactly-one-featured, reorder semantics) need detailed design.
  • NFR Requirements — EXECUTE
    • Rationale: Security Baseline extension is enabled and blocking (D-11); the hosting-extraction unit specifically carries NFR risk (must not regress Api's existing security headers/rate limiting/Sentry/Data Protection).
  • NFR Design — EXECUTE
    • Rationale: Follows directly from NFR Requirements being executed.
  • Infrastructure Design — EXECUTE (primarily for the Client/hosting unit: Api.SlpSoftware is a new deployment target; likely skippable for the Offerings unit, which reuses the existing MariaDB/module-migration infrastructure with nothing new to map)
    • Rationale: Api.SlpSoftware becoming a deployment target is new for this specific unit, even though the underlying hosting infrastructure (Pi, Gitea) already exists — per the "when in doubt, execute" rule for infra that's new to this unit.
  • Code Generation — EXECUTE (ALWAYS)
    • Rationale: Implementation planning and code generation needed for every unit.
  • Build and Test — EXECUTE (ALWAYS)
    • Rationale: Full build across units together, plus integration testing between the new module, the new Client project, and the unchanged Api.

🟡 OPERATIONS PHASE

  • Deployment Setup — EXECUTE (asks its own inclusion question when reached, per the workflow's standard pattern)
    • Rationale: D-7/D-15 — the CI/CD pipeline cutover from Api to Api.SlpSoftware is explicitly in scope for this feature's Operations phase.
  • Monitoring Setup — EXECUTE (asks its own inclusion question when reached)
    • Rationale: The new public endpoint and admin CRUD are new surfaces on what will become the production API; worth confirming the existing Sentry-based monitoring (inherited via FR-3) covers them, or whether anything additional is needed.
  • Production Readiness Validation — EXECUTE (ALWAYS, once Operations phase is reached)
    • Rationale: Standard wrap-up gate, including the Security Baseline final check and (per this repo's convention) the dotnet-appsettings compliance check for the new Client project.

Package Change Sequence (Brownfield)

  1. SlpModularCms.Core — add CmsHost.Configure(...) (or equivalent), extracted from SlpModularCms.Api/Program.cs. Must land first; blocks everything else.
  2. SlpModularCms.Api — repoint Program.cs at the new shared method. No behavior change; verify via existing tests before proceeding.
  3. SlpModularCms.Api.SlpSoftware (new) and SlpModularCms.Modules.Offerings (+ .Tests, new) — can proceed once steps 1-2 are verified; independent of each other internally, both needed before Build and Test can exercise the full stack.
  4. Gitea Actions pipeline (continuous_integration.yaml, deploy-scp.yaml, deployment-instructions.md) — retargeted in the Operations phase only, after Construction has proven steps 1-3.

(Final unit grouping is confirmed in Units Generation — this is the dependency-respecting order that stage should produce.)


Estimated Timeline

  • Total Phases: 3 (Inception remainder, Construction, Operations)
  • Estimated Duration: Not tracked in calendar time for this workflow — driven by stage-by-stage approval, not a schedule.

Success Criteria

  • Primary Goal: SlpModularCms.Api.SlpSoftware exists, hosts Core/Identity/Availability/Master/Offerings, serves the public GET /api/v1/offerings and authenticated admin CRUD, without regressing SlpModularCms.Api.
  • Key Deliverables: Shared CmsHost.Configure(...) in Core; SlpModularCms.Api.SlpSoftware project in Clients; SlpModularCms.Modules.Offerings (+ .Tests) in Application/Modules / Tests/Modules; documented reference content (FR-8); retargeted CI/CD pipeline (Operations).
  • Quality Gates: Full Security Baseline compliance (per requirements.md); Api's existing test suite green after the extraction; new module's own test coverage (NFR-2); Build and Test phase integration checks.
  • Integration Testing: Api.SlpSoftware serving all five modules together, same-origin site + /admin + /api/v1, matches Api's existing behavior for the four pre-existing modules.
  • Operational Readiness: CI/CD pipeline successfully building/deploying Api.SlpSoftware; monitoring/alerting confirmed to cover the new surfaces.