Files
marketplaces/docs/backend/BACKEND-HANDOFF.md
sdarbinyan e5949c3967
Some checks failed
Architecture Governance / architecture (push) Failing after 6m16s
fix(deploy): provision tenant API domains
Reconcile TLS, exact CORS, and backend proxying before release activation so every storefront uses its derived API host.
2026-08-20 15:04:10 +04:00

108 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Backend handoff — start here
Single entry point for a backend developer picking this up cold. Written 2026-08-18.
## 1. What this is
`marketplaces` is a multi-tenant marketplace platform frontend (Angular 22). The frontend is built and waiting; **there is no backend yet**. Every wire contract the backend needs to implement is already written and sitting in this directory — see [README.md](README.md) for the full index and build order.
## 1a. Multi-tenancy — the thing that shapes every endpoint
The final executable infrastructure/backend contract is
[TENANT-API-DOMAIN-HANDOFF.md](TENANT-API-DOMAIN-HANDOFF.md). Follow it for
hostname normalization, CORS, nginx, TLS, CI secrets, and acceptance checks.
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 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. 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.
Constraints already fixed by the frontend design (see the platform-vision facts in `docs/context/`): no marketplace-specific code or hardcoded marketplace data in the frontend; bootstrap carries only what is needed before app start (branding, languages, homepage layout, navigation, enabled widgets, footer pages) and **never** products, orders, cart, or users.
[PHASE-9](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) covers the marketplace registry, domain attachment, and publish/revision model.
## 2. Read in this order
1. [README.md](README.md) — index of all contracts, build order, and what's deliberately excluded.
2. [PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md) — start here. Everything after depends on the money model.
3. Phases 2→4 — the rest of the launch gate (orders, catalog, connectors).
4. [TRACK-S-SECURITY-RBAC-CONTRACT.md](TRACK-S-SECURITY-RBAC-CONTRACT.md) — **gates the launch.** Today the admin role model is decorative: nothing server-side enforces any permission. §8 covers per-marketplace bootstrap admin accounts and self-service sub-admin management.
5. [TRACK-A-ANALYTICS-CONTRACT.md](TRACK-A-ANALYTICS-CONTRACT.md) — longest lead time, start it in parallel with Phase 1.
6. Phases 5→10 — post-launch-gate.
7. [PARTNER-PROVISIONING-API-CONTRACT.md](PARTNER-PROVISIONING-API-CONTRACT.md) — the inbound partner API. Read it **before implementing Phase 1**, not after: it adds `RoutingContext` to `CheckoutSession`/`PaymentIntent`/`Payment` ([Phase 1 §6.5](PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md)) and two levels above `Marketplace` ([Phase 9 §1](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md)). Building the partner API itself can wait; carrying its routing dimension in the payments tables cannot.
[../../BACKEND-API-REFERENCE.md](../../BACKEND-API-REFERENCE.md) documents the *current* live API surface (legacy endpoints, error envelope, mock-only areas). New endpoints use `/api/v2/...` namespaces; legacy endpoints are not being migrated.
## 3. Auth — read before writing any endpoint
Auth is no longer part of this repo. It lives in `@marketplaces/auth`, published from [vitanovaPackages](https://sources.vitanova.network/sdarbinyan/vitanovaPackages.git). See [../PACKAGES-USAGE.md](../PACKAGES-USAGE.md) for the full client surface. What matters on the backend side:
**Two mechanisms exist client-side.**
- **Telegram QR/session (live).** Endpoints under `{authApiUrl}/users/sessions``POST` to create, `GET /{id}` to poll, `DELETE /{id}` to log out. Both customer and admin login call the *same* endpoints; only client-side storage differs. The response shape is normalized permissively client-side (many key spellings accepted), but a clean implementation should return `{ webSessionID, user: { userId, username, firstName, lastName }, status, expiresAt }`.
- **Ed25519 challenge/response (not built).** `GET /api/admin/auth/challenge`, `POST /api/admin/auth/verify`, `POST /api/admin/auth/refresh`, `POST /api/admin/auth/logout`. Contracts in [TRACK-S](TRACK-S-SECURITY-RBAC-CONTRACT.md) and the package's `ed25519/models/auth-api.model.ts`. Until these ship, the client shows a `backend-unavailable` screen — nothing is mocked.
**The critical gap:** the session API has no concept of "admin." The frontend cannot distinguish an admin session from a customer one — it only chooses where to *store* the result. **Every admin endpoint must independently verify authorization server-side.** Client-side guards are UI convenience, never security. This is the single most serious open issue in the system.
Admin requests carry `AdminWebSessionID: <sessionId>` (and `Authorization: Bearer <token>` once admin JWTs exist) on paths containing `/admin/`, `/backoffice/`, `/builder/`, `/media/`.
## 4. Environment / infrastructure state
Dev server `213.21.246.138` (user `seto`, sudo, SSH key provided separately).
| Thing | State |
|---|---|
| nginx 1.24 | **Installed, running.** Config at `/etc/nginx/sites-enabled/marketplaces-dev.conf`. Serves frontend from `/srv/marketplaces/current/frontend`, backoffice from `/srv/marketplaces/current/backoffice`, proxies `/api/``127.0.0.1:8080`. `/health` returns `ok`. |
| Go toolchain | Installed (`/usr/local/bin/go`). |
| Backend service on :8080 | **Not running.** Nothing is listening. `/srv/marketplaces/current/api` is an empty shell. nginx's `/api/` proxy currently 502s. |
| PostgreSQL | **Installed but inactive.** Needs starting, a database, a user, and schema before anything works. |
| Shared packages | `@marketplaces/auth` installs over plain git from a release branch — no registry, token, or tunnel needed. `npm install` works out of the box. |
| Verdaccio (npm registry) | Running in Docker on port 4873, but **superseded and unused** — nothing depends on it. See [../PACKAGE-EXTRACTION.md](../PACKAGE-EXTRACTION.md) §5. |
| Firewall (ufw) | Active. 80/tcp, 443/tcp, OpenSSH. |
| TLS / certbot | **Not installed.** No certificates. Everything is plain HTTP today. For multi-tenant this is real work: every customer domain needs a certificate (per-domain issuance, or a wildcard if all tenants sit under one apex). |
| DNS / dynamic subdomains | **Not set up.** No domain currently points at the server (reverse DNS is the provider default `silky-bronze.ptr.network`). No wildcard record, no per-tenant subdomain automation, no Hostinger DNS integration. The *application* is fully multi-tenant (§1a) — this is the missing infrastructure underneath it. [PHASE-9](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md) specifies the target. |
| Frontend deploy (CD) | **None.** Pushing to `main` deploys nothing. `architecture-governance.yml` builds and checks boundaries but has no deploy step, and nothing writes to `/srv/marketplaces/current/frontend`. Deploys are manual today. |
| CI runner | None on this server; `sources.vitanova.network` CI runs elsewhere. |
## 5. To get a working dev environment
Nothing here is done yet — this is the setup a backend dev does on day one.
1. Start and configure PostgreSQL; create the database and application user.
2. Design the schema from the Phase 14 contracts (schema design is explicitly the backend's own call — the contracts specify entities, endpoints, and invariants, never tables). Tenant scoping belongs in the schema from day one; retrofitting it is painful.
3. Build the API service, listen on `127.0.0.1:8080`. nginx already proxies `/api/` to it.
4. Implement the **bootstrap config endpoint** (§1a) — without it the frontend cannot render for any tenant.
5. Implement the Telegram session endpoints — the login flow is fully built client-side and blocked only on these.
6. Implement `GET /api/identity/v1/session/permissions` ([TRACK-S §2](TRACK-S-SECURITY-RBAC-CONTRACT.md)) — frontend route guards derive from it.
7. Seed per-marketplace bootstrap admins ([TRACK-S §8](TRACK-S-SECURITY-RBAC-CONTRACT.md)): login = marketplace slug, password = `{slug}2026$`, `mustChangePassword: true`.
Steps 46 unblock the entire frontend. Everything after is feature work.
## 6. Frontend deploy
```bash
git clone <marketplaces repo>
npm install # pulls @marketplaces/auth over git, no credentials needed
npm run build # -> dist/dexarmarket
```
Angular 22, Node 24+. nginx serves `/srv/marketplaces/current/frontend`.
[`deploy.yml`](../../.github/workflows/deploy.yml) builds and atomically deploys
pushes to `main`; one deployment updates every domain at once. Before activation,
the workflow reconciles TLS, exact CORS, and reverse proxying for every host in
`STOREFRONT_DOMAINS`. Production deployment requires the documented CI secrets
and the one-time [`server-setup.sh`](../../scripts/deploy/server-setup.sh) run.
## 7. Known open decisions
- Registry reachability for CI (reverse proxy + TLS, or a different registry entirely).
- ~~Backend ownership.~~ Answered 2026-08-18: implemented by a separate backend developer against this contract set.
- Additional payment providers (wallets, BNPL) — [Phase 7 §4](PHASE-7-PAYMENTS-RECONCILIATION-CONTRACT.md).
- Per-connector marketplace adapters — written per partner at onboarding, [Phase 4 §8](PHASE-4-CONNECTOR-FRAMEWORK-CONTRACT.md).
- Backfill of `Company`/`Project`/`PaymentPoint` for existing marketplaces — sequence specified in [Phase 9 §1.2](PHASE-9-TENANT-REGISTRY-DOMAINS-CONTRACT.md), not yet scheduled.