feat: serve isolated companies below a fixed product path
All checks were successful
All checks were successful
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
09e2239bc6
commit
9345a1bb1a
28 changed files with 350 additions and 117 deletions
16
docs/evidence/2026-09-11-tenant-path-browser.json
Normal file
16
docs/evidence/2026-09-11-tenant-path-browser.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"status": "passed",
|
||||
"checks": [
|
||||
"Edge matches only the exact company prefix",
|
||||
"Bare company path canonicalizes and anonymous access reaches prefixed login",
|
||||
"Prefixed CSS and JavaScript load and render the login controls",
|
||||
"Real CSRF login, cookie scope and dashboard navigation stay within the tenant path",
|
||||
"Password-change navigation and CSRF logout preserve the prefix",
|
||||
"Expired HTMX requests demand full prefixed login",
|
||||
"Mobile login fits and browser has no JavaScript errors"
|
||||
],
|
||||
"synthetic_users": true,
|
||||
"disposable_sqlite": true,
|
||||
"local_http_only": true,
|
||||
"production_edge_admitted": false
|
||||
}
|
||||
31
docs/tenant-path-deployment.md
Normal file
31
docs/tenant-path-deployment.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Deploy an isolated company below the product hostname
|
||||
|
||||
For the demo pilot, use `https://vergabe-teilnahme.coulomb.social/demo-company/`.
|
||||
Configure the isolated application with `APP_BASE_PATH=/demo-company` and
|
||||
`ALLOWED_HOSTS=vergabe-teilnahme.coulomb.social`. The external CSRF origin is
|
||||
`https://vergabe-teilnahme.coulomb.social`, without a path.
|
||||
|
||||
The edge matches exactly `/demo-company` or the `/demo-company/` path prefix,
|
||||
redirects the bare path to its trailing-slash form, and strips `/demo-company`
|
||||
before forwarding. Internal health remains `/health/`. Django's fixed
|
||||
FORCE_SCRIPT_NAME generates the external URLs. Untrusted forwarded-prefix
|
||||
headers never select a tenant or override this configuration. Keep static and
|
||||
private media requests on this same application route.
|
||||
|
||||
Each tenant keeps its own namespace, database, media volume and issue-state
|
||||
volume. A URL path is a deployment selector, not an authentication claim.
|
||||
Cookies use company-specific names and paths; cookies and paths are not separate
|
||||
browser origins. Only this trusted product's instances share the product host.
|
||||
Django accounts still provide product admission; native platform tenant creation
|
||||
and membership do not by themselves implement product SSO.
|
||||
|
||||
Omit APP_BASE_PATH for the existing root-path deployment behavior. Nonempty
|
||||
values must be one lowercase tenant slug prefixed with `/`; traversal, nested
|
||||
paths and external URLs are refused at startup.
|
||||
|
||||
Validation: 94 existing application tests plus four tenant-path regressions;
|
||||
Vite asset build; seven local Chromium checks through an exact-path/strip-prefix
|
||||
edge fixture. Authentication/CSRF, password changes, navigation/HTMX, private
|
||||
media, cookie scope, assets and mobile layout are covered. These checks use a
|
||||
disposable SQLite database and synthetic users, and do not establish live DNS,
|
||||
TLS, database custody or restore readiness. RAPPS-WP-0014 owns those live gates.
|
||||
Loading…
Add table
Add a link
Reference in a new issue