90ac0b81d1
Add full V2 architecture: identity, content, studio (.NET 10) and file, render, notification, gateway (Go) services with vendored deps, plus DB migrations, event/API contracts, and an init-db script. Wire the Next.js frontend to the gateway: server-side JWT auth routes (login/register/refresh/logout/me), gateway fetch helper, and session/ cookie/jwt helpers under src/lib. Containerize the stack via docker-compose.v2.yml and per-service Dockerfiles. Base images resolve through a Nexus mirror (Docker Hub) and MCR directly; npm/NuGet pull from Nexus groups. Self-host fonts via next/font/local to avoid Google Fonts (geo-blocked). Add CI workflow and ignore .env.v2, *.stackdump, and .NET bin/obj. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
FlatRender V2 — Service Contracts
This directory defines all inter-service contracts. Services are loosely coupled — they communicate via REST APIs (synchronous) and RabbitMQ events (asynchronous). The browser connects to the Gateway over HTTPS + WebSocket.
Layout
contracts/
├── common/ # Reusable OpenAPI components (Error, Pagination, ...)
│ └── types.yaml
├── events/ # RabbitMQ event schemas (JSON Schema)
│ ├── README.md # Event catalog with routing keys
│ ├── render.yaml
│ ├── node.yaml
│ ├── identity.yaml
│ ├── file.yaml
│ ├── tenant.yaml
│ └── notification.yaml
├── websocket/ # WebSocket message protocol
│ └── render-progress.md
└── rest/ # Per-service OpenAPI 3.0 specs
├── identity.openapi.yaml # internal
├── content.openapi.yaml # internal
├── studio.openapi.yaml # internal
├── render.openapi.yaml # internal
├── file.openapi.yaml # internal
├── notification.openapi.yaml # internal
├── node-agent.openapi.yaml # called by render orchestrator
├── gateway-public.openapi.yaml # what frontend uses
└── reseller-api.openapi.yaml # B2B API (api-key auth)
Authentication
| Surface | Auth | Carries |
|---|---|---|
| Gateway public API | JWT (Bearer) | user_id, tenant_id |
| Reseller API | API key (X-API-Key + signature) | tenant_id, scopes |
| Internal service API | Service token (mTLS in prod) | service_name |
| Node Agent API | Shared secret (HMAC) | orchestrator_signature |
| WebSocket | JWT in query param ?token=... |
user_id, job_id |
Versioning
- REST: URL prefix
/v1/... - Events: routing key suffix
.v1 - WebSocket: protocol negotiation header
Conventions
- All IDs are UUID v4
- All timestamps ISO 8601 with timezone (
2026-05-27T10:15:00Z) - All money fields are
_minorintegers (rial / cent) - All durations are seconds (numeric)
- All file sizes are bytes (integer)
- Pagination:
?page=1&page_size=20returningPaginatedResponse<T> - Errors:
{ "error": { "code", "message", "details", "trace_id" } } - Tenant context:
X-Tenant-Idheader on internal calls (JWT carries it on public)