feat: V2 microservices stack — backend services, gateway, JWT auth
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>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# RabbitMQ Event Catalog
|
||||
|
||||
All async communication between services uses RabbitMQ. Events follow
|
||||
strict naming: `{domain}.{entity}.{verb}.v{n}` (past tense).
|
||||
|
||||
## Exchanges
|
||||
|
||||
| Exchange | Type | Purpose |
|
||||
|---------------------------|----------|--------------------------------------|
|
||||
| `flatrender.events` | topic | Domain events (fan-out by routing) |
|
||||
| `flatrender.render` | direct | Render job dispatch (per queue) |
|
||||
| `flatrender.notify` | direct | Notification dispatch (per channel) |
|
||||
| `flatrender.dlq` | fanout | Dead-letter queue |
|
||||
|
||||
## Common envelope
|
||||
|
||||
Every message body has this shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"event_id": "uuid",
|
||||
"event_type": "render.job.completed.v1",
|
||||
"event_time": "2026-05-27T10:15:00Z",
|
||||
"tenant_id": "uuid",
|
||||
"user_id": "uuid",
|
||||
"trace_id": "uuid",
|
||||
"correlation_id": "uuid",
|
||||
"producer": "render-orchestrator",
|
||||
"data": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
## Headers (AMQP)
|
||||
|
||||
| Header | Required | Notes |
|
||||
|---------------------|----------|------------------------------------------------|
|
||||
| `content-type` | yes | `application/json` |
|
||||
| `content-encoding` | yes | `utf-8` |
|
||||
| `x-event-type` | yes | Same as `event_type` (for routing convenience) |
|
||||
| `x-tenant-id` | yes | For tenant-aware consumers |
|
||||
| `x-trace-id` | yes | Distributed tracing |
|
||||
| `x-retry-count` | optional | Incremented on requeue |
|
||||
| `x-max-retries` | optional | Default 3 |
|
||||
|
||||
## Routing keys (topic exchange `flatrender.events`)
|
||||
|
||||
```
|
||||
identity.user.registered.v1
|
||||
identity.user.email_verified.v1
|
||||
identity.user.banned.v1
|
||||
identity.tenant.created.v1
|
||||
identity.tenant.suspended.v1
|
||||
identity.plan.activated.v1
|
||||
identity.plan.expired.v1
|
||||
identity.payment.succeeded.v1
|
||||
identity.payment.failed.v1
|
||||
identity.payment.refunded.v1
|
||||
identity.api_key.created.v1
|
||||
identity.api_key.revoked.v1
|
||||
|
||||
content.template.published.v1
|
||||
content.template.unpublished.v1
|
||||
content.font.installed.v1
|
||||
content.svg_preview.generated.v1
|
||||
|
||||
studio.project.saved.v1
|
||||
studio.project.deleted.v1
|
||||
|
||||
render.job.queued.v1
|
||||
render.job.started.v1
|
||||
render.job.progress.v1
|
||||
render.job.completed.v1
|
||||
render.job.failed.v1
|
||||
render.job.cancelled.v1
|
||||
render.snapshot.requested.v1
|
||||
render.snapshot.ready.v1
|
||||
|
||||
node.online.v1
|
||||
node.offline.v1
|
||||
node.crashed.v1
|
||||
node.heartbeat.v1
|
||||
node.cache.updated.v1
|
||||
|
||||
file.uploaded.v1
|
||||
file.processed.v1
|
||||
file.deleted.v1
|
||||
file.quota_warning.v1
|
||||
file.quota_exceeded.v1
|
||||
file.cleanup.scheduled.v1
|
||||
file.cleanup.executed.v1
|
||||
|
||||
notification.created.v1
|
||||
notification.delivered.v1
|
||||
notification.failed.v1
|
||||
|
||||
tenant.usage.recorded.v1
|
||||
tenant.webhook.fired.v1
|
||||
tenant.webhook.failed.v1
|
||||
```
|
||||
|
||||
## Render dispatch (direct exchange `flatrender.render`)
|
||||
|
||||
```
|
||||
render.queue.snapshot
|
||||
render.queue.vip
|
||||
render.queue.paid
|
||||
render.queue.preview
|
||||
render.queue.mockup
|
||||
render.queue.voiceover
|
||||
```
|
||||
|
||||
Each queue has priority `x-max-priority: 10`. Job priority encoded in
|
||||
message priority property.
|
||||
|
||||
## Notification dispatch (direct exchange `flatrender.notify`)
|
||||
|
||||
```
|
||||
notify.channel.push
|
||||
notify.channel.email
|
||||
notify.channel.sms
|
||||
notify.channel.telegram
|
||||
notify.channel.webhook
|
||||
```
|
||||
|
||||
## Dead-letter routing
|
||||
|
||||
Failed messages (after `x-max-retries` exhausted) are republished to
|
||||
`flatrender.dlq` with original routing key preserved in
|
||||
`x-original-routing-key` header.
|
||||
Reference in New Issue
Block a user