Files
marketplaces/docs/backend/BACKEND-HANDOFF.md
sdarbinyan 551a22a245
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
fix: install shared packages over git, unbreaking CI
The Verdaccio registry introduced earlier is unreachable from CI (listens on
127.0.0.1:4873 behind a firewall allowing only 80/443/SSH), which broke the
architecture-governance workflow - its npm ci step could no longer resolve
@marketplaces/auth.

Packages are now published to git release branches (release/auth,
release/payment in vitanovaPackages) whose root is the package itself, and
installed with git+<repo>#release/auth. No registry, token, tunnel, or CI
secret - anonymous git read is enough.

- package.json: git dependency; .npmrc removed (no scope mapping needed)
- vitanovaPackages release.yml rebuilt to force-push release branches
- ADR-0001 amended with the distribution change and why the registry lost
- BACKEND-HANDOFF: added the multi-tenancy section (hostname -> tenantKey ->
  per-tenant bootstrap config), corrected the install and deploy notes, and
  recorded that no CD pipeline exists
- PACKAGE-EXTRACTION / PACKAGES-USAGE rewritten for the git-branch flow

Verified: npm ci, arch:check:boundaries, ng build, 103/103 tests, all with
no credentials configured.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 02:08:05 +04:00

96 lines
9.0 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
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) derives a `tenantKey` from `window.location.hostname` (first label; `www.` skipped; localhost falls back to a configured key).
2. [`ApiConfigService`](../../src/app/core/config/api-config.service.ts) turns that key into the API base URL — via an explicit per-tenant map or a `{tenant}` URL template.
3. `ApiBootstrapProvider` fetches that tenant's **bootstrap config**, which drives branding, theme, locales, currencies, navigation, footer, and which pages exist.
4. nginx is `default_server` / `server_name _`, so any domain pointed at the server IP gets the same bundle and self-resolves.
**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.
[../../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 20+. nginx serves `/srv/marketplaces/current/frontend`, so deploying means copying `dist/dexarmarket` there — **manually, today.** There is no CD pipeline. Because of the multi-tenant design (§1a), one such deploy updates every domain at once.
## 7. Known open decisions
- Registry reachability for CI (reverse proxy + TLS, or a different registry entirely).
- Backend ownership was still unnamed as of Sprint 0.1.
- 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).