# Domain Entities — U1 Hosting & Serving **Note**: U1 introduces **no persisted entity**. It adds no table, no migration and no database column. Its "domain" consists of in-memory configuration descriptors and a response model. They are documented here because they are the data structures the unit's logic operates on, and because reviewers should be able to confirm that nothing is being persisted. --- ## Concept Relationships ```mermaid graph TD host["Host application"] mountweb["StaticMount: website
request path /"] mountadmin["StaticMount: admin SPA
request path /admin"] provider["File provider
per mount"] fallbackweb["SPA fallback: website"] fallbackadmin["SPA fallback: admin"] placeholder["Placeholder page
embedded resource"] report["HealthReport
response model"] orchestrator["ModuleOrchestrator
existing"] bypass["Bypass prefix list
existing, extended"] tokenparams["Token validation parameters
existing, now shared"] host -->|"registers"| mountweb host -->|"registers"| mountadmin mountweb -->|"resolves files via"| provider mountadmin -->|"resolves files via"| provider mountweb -->|"falls back to"| fallbackweb mountadmin -->|"falls back to"| fallbackadmin fallbackweb -->|"substitutes when index absent"| placeholder host -->|"exposes"| report report -->|"reads module names from"| orchestrator host -->|"configures"| bypass host -->|"shares"| tokenparams bypass -->|"used by availability gate"| tokenparams classDef hostnode fill:#90cdf4,stroke:#2b6cb0,stroke-width:1px,color:#000; classDef mount fill:#9ae6b4,stroke:#2f855a,stroke-width:1px,color:#000; classDef model fill:#fbd38d,stroke:#c05621,stroke-width:1px,color:#000; classDef existing fill:#e2e8f0,stroke:#4a5568,stroke-width:1px,color:#000; class host hostnode; class mountweb,mountadmin,provider,fallbackweb,fallbackadmin,placeholder mount; class report model; class orchestrator,bypass,tokenparams existing; ``` Text alternative: the host registers two independent static mounts each with its own file provider and SPA fallback, plus a health response model that reads module names from the existing orchestrator; the bypass list and token validation parameters are existing structures this unit extends and shares. --- ## Static Mount Descriptor (configuration, in-memory) Not a class to be persisted — this describes what each `UseStaticFiles` registration is configured with. | Field | Website mount | Admin mount | |---|---|---| | Physical root | `{contentRoot}/wwwroot/web` | `{contentRoot}/wwwroot/admin` | | Request path | `""` (root) | `/admin` | | Default file | `index.html` | `index.html` | | Directory browsing | Disabled | Disabled | | Tolerates missing root | **Yes** — logs a warning | Yes — logs a warning | | Registration order | Second | **First** | **Registration order matters**: the admin mount must be registered first, or `/admin/...` would be resolved against the website root. --- ## HealthReport (response model, not persisted) | Field | Type | Purpose | |---|---|---| | `status` | string | `"Healthy"`. A running process always reports healthy; absence of a response is the unhealthy signal | | `timestamp` | timestamp with offset | When the report was produced, so a cached response is recognisable | | `version` | string | The application's informational version, so a deploy can be confirmed without host access | | `modules` | string array | Names of modules loaded by `ModuleOrchestrator` | **Validation and constraints**: - Every field is derived from in-process state. No field may require a database query, file read or network call (BR-U1-15). - No field may contain configuration values, paths, connection details or environment variable contents (BR-U1-18). - `modules` is read from the existing `ModuleOrchestrator.ModuleNames`, which is already exposed anonymously by `/api/v1/System/capabilities` — so this field introduces no new disclosure. --- ## Placeholder Page (embedded static content) | Property | Value | |---|---| | Storage | Embedded resource in the assembly, not a file in `wwwroot` | | Served when | The website fallback is needed and `wwwroot/web/index.html` is absent | | Status code | `200` | | Content | A statement that no website has been deployed yet, the expected target path, and a link to `/admin` | **Why embedded rather than a file**: a file in `wwwroot/web/` would be inside the directory a website workspace owns and overwrites — it would be deleted by the first real website deployment, or worse, mistaken for part of the customer's site. Embedding keeps it outside that boundary entirely. **What it must not contain**: no version, no environment name, no module list, no configuration. It is served anonymously to any visitor of the site root, which is a wider audience than `/health`. --- ## Extended Existing Structures ### Bypass prefix list (`AvailabilityMiddleware`) | Aspect | Detail | |---|---| | Current contents | `/api/v1/Availability/status`, `/api/v1/Auth/`, `/api/v1/Setup/status`, `/api/v1/master/`, `/api/v1/SlaveStatus` | | Added by U1 | `/health` | | Matching | Case-insensitive prefix match, unchanged | ### Shared token validation parameters | Aspect | Detail | |---|---| | Currently | Configured once inside `AddJwtBearer` in `ServiceCollectionExtensions.AddCoreInfrastructure` | | Change | Extracted so the same instance is used by both the bearer scheme and the availability gate | | Constraint | Exactly one definition. Two copies could drift, and a gate more permissive than the scheme would silently re-open the hole FR-24 closes | --- ## Persistence Summary | Question | Answer | |---|---| | New tables? | None | | New migrations? | None | | New columns? | None | | New configuration sections? | None — U1 adds no `appsettings` section | | Anything written to disk at runtime? | No | All persistence work in Round 1 belongs to **U2**, which adds the Data Protection keys table and the automatic Core migration.