Files
marketplaces/docs/backend/BACKEND-HANDOFF.md
sdarbinyan 98c39f6844
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Deploy Frontend / deploy (push) Has been cancelled
fix(auth): clarify admin login flow
Use admin-specific Telegram copy and define the missing credential API. Replace predictable bootstrap passwords with random one-time secrets.
2026-08-21 07:39:30 +04:00

10 KiB
Raw Blame History

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 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. 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 reads the complete current browser hostname and protocol (localhost still uses the development proxy).
  2. ApiConfigService uses one API host per base domain: both example.com and store1.example.com use api.example.com.
  3. ApiBootstrapProvider, auth, legacy API calls, and versioned /api/... calls all use that same base.
  4. Each base domain owns one API DNS/TLS/reverse-proxy entry. nginx validates the browser origin and forwards the complete storefront hostname as X-Storefront-Host.
  5. Backend tenant lookup uses that trusted storefront hostname, not the shared API 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). 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 covers the marketplace registry, domain attachment, and publish/revision model.

2. Read in this order

  1. README.md — index of all contracts, build order, and what's deliberately excluded.
  2. 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.mdgates 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 — longest lead time, start it in parallel with Phase 1.
  6. Phases 5→10 — post-launch-gate.
  7. 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) and two levels above Marketplace (Phase 9 §1). Building the partner API itself can wait; carrying its routing dimension in the payments tables cannot.

../../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. See ../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/sessionsPOST 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 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 §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 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) — frontend route guards derive from it.
  7. Seed per-marketplace bootstrap admins (TRACK-S §8): login = marketplace slug, cryptographically random one-time password delivered out of band, mustChangePassword: true.

Steps 46 unblock the entire frontend. Everything after is feature work.

6. Frontend deploy

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 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 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.
  • Per-connector marketplace adapters — written per partner at onboarding, Phase 4 §8.
  • Backfill of Company/Project/PaymentPoint for existing marketplaces — sequence specified in Phase 9 §1.2, not yet scheduled.