Backend Services
The backend monorepo (os-backend/) manages each service as a git submodule under services/, orchestrated with pnpm workspaces and Docker Compose. The NestJS services share a common library, shared/os-nest-shared (exception filter, logging/response interceptors, validation pipe, Swagger setup).
os-auth-service — Spring Boot / Java 21
The identity and organization service. Besides authentication it co-hosts the user-management capability in v1: users, invitations, roles/permissions, departments and memberships, projects, and badges.
- Port 8081 · DB
os_auth(Flyway migrationsV1–V13, JPA validates only) - Layout: hexagonal —
api/(controllers, DTOs),application/,domain/{model,repository,service},infrastructure/{persistence,messaging,integration,web}undercom.ipf.os.auth. - Auth flows: Google Workspace sign-in (hosted-domain restricted; a Google identity alone is not enough — the user must be provisioned and
ACTIVE), local email/password only for the fallback/root admin, JWT access tokens + rotating refresh tokens. - Messaging: RPC responder on the
os.rpcdirect exchange — answersauth.department.get-by-id,auth.project.get-by-id, andauth.pmo.getlookups for the tickets service. - Seeding: Flyway seeds the RBAC catalog; startup initializers can create a bootstrap admin and Google test identities (toggled by
AUTH_BOOTSTRAP_*env vars). - No Swagger — its API contract lives only in the hand-written
docs/design/api-spec.yml.
os-tickets-service — NestJS
The flagship domain service: tickets, participants, comments, attachments, SLA policies, an append-only action timeline, and relative tickets.
- Port 8086 · DB
os_tickets(TypeORM migrations) - Key domain rules (enforced server-side):
- Statuses are forward-only:
OPEN → IN_PROGRESS → CLOSED. There is no reopen — continuation happens through relative tickets (parentId/rootId, parent flaggedrevised). - Priority is derived from the due date, never accepted from the client: ≤ 4h Critical, ≤ 24h High, ≤ 3d Medium, else Normal (no due date → Normal with a 7-day SLA).
- Ticket numbers follow
T-YYYY-WW-####from an atomic per-ISO-week counter. - Assignment resolves most-specific-wins: direct assignee > project (PMO + PM) > department manager; participant roles are
ASSIGNEE | MANAGER | PMO | PM | OBSERVER.
- Statuses are forward-only:
- Messaging: RPC client on
os.rpcfor department/project/PMO enrichment (3s timeout, degrades gracefully — a ticket still loads withowningDepartment: null); publisher on theos.eventstopic exchange with routing keysticket.<eventtype>. - Attachments are stored in MinIO and accessed through presigned URLs (max 10 files, size caps, MIME whitelist).
os-integration-service — NestJS
The notification service. Consumes ticket events and persists in-app notifications; serves notification reads. Outbound email and Google adapters are designed but deferred.
- Port 8087 · DB
os_integration - Messaging: binds queue
integration.notificationstoos.eventswith routing keyticket.*, dead-letter queue included. The event contract is pinned and mirrors the publisher:ASSIGNED,PARTICIPANT_ADDED,COMMENT_ADDED,INTERNAL_NOTE_ADDED,CLOSED_NEEDS_RESPONSE,SLA_BREACHED,RELATIVE_CREATED.
os-meals-service — NestJS
Designed to own the meal library, weekly menus, and selections.
- Port 8083 · DB
os_meals - Status: the service is scaffolded (health endpoint, config, database wiring) but the meals domain module, entities, and migrations are not yet implemented in this repo — the data model exists only in
docs/design/data-model.md. Verify against the code before relying on meals endpoints.
os-hr-service and os-tasks-service — placeholders
Both are declared submodules with no code. HR (leave, approvals, profiles) is planned at /api/v1/hr. Note the backend README's service table is partly stale — tickets live in os-tickets-service, not os-tasks-service.
Working on a NestJS service
cd os-backend/services/os-tickets-service
pnpm build # prebuild compiles shared/os-nest-shared first
pnpm start:dev # watch mode
pnpm test # jest --runInBand
pnpm typecheck
pnpm migration:generate / migration:run / migration:revert
Each Nest service serves Swagger UI at /api/v1/docs on its own port when SWAGGER_ENABLED=true — but the gateway does not route it, so hit the service port directly.