vergabe-teilnahme/docs/tenant-path-deployment.md
tegwick 9345a1bb1a
All checks were successful
Application acceptance / application-tests (push) Successful in 1m12s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 25s
feat: serve isolated companies below a fixed product path
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
2026-09-11 21:29:26 +02:00

1.9 KiB

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.