fix(api): derive host from storefront domain
Some checks failed
Architecture Governance / architecture (push) Has been cancelled

Every storefront, including nested subdomains, uses its matching api.<hostname> endpoint.
This commit is contained in:
2026-08-20 14:31:22 +04:00
parent f4ea4c7af8
commit 640360d63c
15 changed files with 88 additions and 120 deletions

View File

@@ -10,11 +10,11 @@ Single entry point for a backend developer picking this up cold. Written 2026-08
One deployed bundle serves **every customer domain**. There is no per-tenant build. The chain is:
1. [`TenantResolverService`](../../src/app/core/config/tenant-resolver.service.ts) reads the current browser hostname/origin (localhost still uses the development proxy).
2. [`ApiConfigService`](../../src/app/core/config/api-config.service.ts) resolves one same-origin API base: `{origin}/backend`.
1. [`TenantResolverService`](../../src/app/core/config/tenant-resolver.service.ts) reads the complete current browser hostname and protocol (localhost still uses the development proxy).
2. [`ApiConfigService`](../../src/app/core/config/api-config.service.ts) prefixes that hostname with `api.`: `example.com` becomes `api.example.com`; `store1.example.com` becomes `api.store1.example.com`.
3. `ApiBootstrapProvider`, auth, legacy API calls, and versioned `/api/...` calls all use that same base.
4. nginx owns `/backend/`, strips that prefix, proxies to the backend, and preserves the original `Host` so the backend can resolve the tenant server-side.
5. nginx is `default_server` / `server_name _`, so any domain pointed at the server IP gets the same bundle and self-resolves.
4. Each derived API hostname owns DNS, TLS, CORS, and a reverse proxy to the backend.
5. Backend tenant lookup recognizes `api.<storefront-host>` as the API alias of `<storefront-host>`; frontend nginx remains `default_server` / `server_name _`, so any attached storefront domain receives the same bundle.
**What this means for you:** the bootstrap endpoint is the single most important thing to build after auth. Every request must be tenant-scoped server-side, and a tenant must never be able to read another tenant's data — return `403`, not an empty result (see [TRACK-S §2](TRACK-S-SECURITY-RBAC-CONTRACT.md)). The frontend supplies the tenant identity from the hostname; the backend must treat that as an untrusted hint and derive real scope from the authenticated session.