Appearance
Architecture
Devopsify is a pnpm and Turborepo monorepo. The API is the authorization and side-effect admission boundary; the worker performs durable asynchronous work; the web app is a client; and shared packages hold contracts and deterministic domain engines.
Request-to-worker boundary
text
browser / CI / agent
|
| HTTPS + session bearer, cookie, or API key
v
+-----------+ validate DTO, tenant, permission,
| Fastify |------> entitlement, policy, approval state
| API | before every side effect
+-----+-----+
| +------------------+
| persist intent, audit | PostgreSQL |
+------------------------>| tenant records, |
| | audit, job state |
| enqueue +------------------+
v ^
+-----------+ progress/results |
| BullMQ |------------------------------+
| Worker | Redis queue + lock
+-----+-----+
|
+--> provider adapter / OpenTofu runner / CI adapter / agentThe queue is not the system of record. A BackgroundJobRecord in PostgreSQL records status, progress, result and error. If REDIS_URL is unset, the same handlers run inline for tests and demo mode.
Service boundaries
| Boundary | Owns | Must not do |
|---|---|---|
| API | Authentication, membership, permissions, entitlements, policy checks, DTO validation, request IDs, audit writes | Trust organizationId, let the model authorize, put credentials in generated artifacts |
| Worker | Discovery, reconciliation, cost rollups, provisioning execution, AI execution, pipeline polling, verification, webhook delivery | Bypass the API's admission checks or treat queue state as durable truth |
| Cloud adapter | Provider credential validation, capability manifest, discovery, resource detail, health, cost estimate and normalized actions | Claim live execution when using a mock adapter |
| Provisioning | Immutable plan/run lifecycle, allowlisted templates, OpenTofu runner boundary, encrypted artifacts and state | Download arbitrary modules or render provider credentials |
| AI service | Context assembly, redaction, typed tool proposals and approval state | Use unrestricted shell, change permissions, approve itself or claim success |
| On-prem agent | Outbound polling, signed typed commands and host-local execution | Open an inbound control port or execute arbitrary shell strings |
| Web app | Presentation and user input | Enforce authorization only in the UI or import backend internals |
Data boundaries
Every tenant-owned record carries organizationId. The server derives it from the authenticated JWT claim after checking membership. Public IDs are UUID v4; mutable records use optimistic versions; money uses decimal values; audit records are append-only evidence. Operational projections such as a resource row may change, but they point back to the observation or job that produced them.
The Digital Twin adds immutable observed and desired snapshots. A plan is bound to snapshot IDs and digests and is revalidated by both the API and worker before the first side effect. It is evidence and planning state, not a provider view and not an authorization boundary.
Package boundaries
@devopsify/contracts owns Zod schemas and generated API types. @devopsify/auth, @devopsify/crypto, @devopsify/entitlements, @devopsify/policy, @devopsify/cloud-adapters, @devopsify/provisioning, @devopsify/ai-devops, @devopsify/agent-protocol and @devopsify/ci-adapters are independently testable. Apps consume these packages through workspace imports.
See ARCHITECTURE_DECISIONS.md in the repository root for the authoritative shared contract. In particular, the contract API namespace is /api/v1; health and Swagger remain root operational endpoints.