Design. Compile. Play.
Quick Start · API Reference · Ecosystem · Contributing
lunaris-app-backend is the Mission Orchestration Engine behind Lunaris — a multi-tenant B2B platform that lets AAA studios rebalance, patch, and ship quest logic without rebuilding the game binary.
It receives mission graphs authored on the Canvas editor, validates them against a strict DAG contract (no cycles, no dead-ends, no dangling edges), compiles each approved graph into an immutable versioned snapshot identified by a SHA-256 hash, and serves the active version to the Unreal Engine 5 plugin through an M2M REST API authenticated by per-organization API keys.
The model is tenant-isolated end-to-end: User × Organization × Workspace × Mission × MissionVersion. Studios cannot see each other's data; every query is scoped by organizationId.
| Repository | Role |
|---|---|
| lunaris-app-backend ← you are here | Validator, compiler, versioning and REST API |
| lunaris-app-frontend | React Flow canvas for Game Designers |
| lunaris-app-unreal | UE5 C++ plugin — consumes the compiled contract at runtime |
- Node.js 24+
- npm 10+ (bundled with Node 24)
- PostgreSQL 15+
git clone https://github.com/lisboon/lunaris-app-backend.git
cd lunaris-app-backend
cp .env.example .env
# Required: DATABASE_URL, JWT_SECRET
# Optional: PORT (3001), JWT_EXPIRES_IN (7d), CORS_ORIGINS
npm install
npx prisma migrate dev
npm run start:devServer starts at http://localhost:3001. Swagger UI is available at /api-docs.
The full, up-to-date reference lives as an Insomnia collection at docs/api/insomnia.json — import it to get every route, header, body shape and example response ready to fire.
The API is organized into three surfaces:
- Auth — signup (creates
User+Organizationatomically), login, session context. Issues a JWT carrying{ userId, memberId, organizationId, role }. - Orchestration (
/workspaces,/missions,/missions/:id/versions,/invites,/members, ...) — the authenticated surface consumed by the Canvas. Every write is scoped to the caller's organization and gated byMemberRole(VIEWER < DESIGNER < ADMIN). - Engine (M2M) —
GET /missions/engine/:id/activeauthenticated viax-api-key. This is what the UE5 plugin calls to fetch the compiledmissionDataresolved to the currently published version hash. Keys are generated under/api-keysand stored HMAC-hashed.
- Runtime — Node.js 24, TypeScript 5.7
- Framework — NestJS 11 on Express
- Build — SWC
- Persistence — Prisma 7 + PostgreSQL
- Auth —
@nestjs/jwt,bcrypt, per-organization HMAC-hashed API keys - Security — Helmet,
@nestjs/throttler, globalValidationPipe(whitelist + forbidNonWhitelisted) - Validation —
class-validator/class-transformer, Notification pattern in domain entities - Docs — Swagger (
@nestjs/swagger) + Insomnia collection - Testing — Jest 30,
supertest(e2e) - Tooling — ESLint 9, Prettier 3, commitlint, husky
Architecture is DDD + Clean: pure domain under src/modules/ (entities, use cases, gateways, facades), NestJS adapters and Prisma under src/infra/. The infra layer depends on modules — never the reverse.
Contributions are welcome. Start with CONTRIBUTING.md for the workflow, and CLAUDE.md for architecture conventions, naming rules and tenancy invariants you'll need to respect before opening a pull request.