feat: Fleet Forge UEM - device management, agent, remote desktop (VNC), TLS reverse proxy

This commit is contained in:
Pepe44DEV
2026-09-06 22:09:28 +00:00
commit db16ad5cc1
154 changed files with 22920 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# ADR-001: Monorepo with pnpm Workspaces
## Status
Accepted
## Context
Fleet Forge requires multiple packages: API server, web dashboard, shared types, and the Go agent. We need a structure that supports shared code, independent builds, and a single repository.
## Decision
Use pnpm workspaces for the TypeScript/Node.js packages. The Go agent lives in the same repo but is built independently.
## Rationale
- pnpm workspaces provide efficient dependency management with a single lockfile
- Workspace references (`workspace:*`) enable local development without publishing
- Compatible with Next.js, Express, and Drizzle ORM
- The Go agent uses standard Go modules independently
## Consequences
- All TS packages share a common `tsconfig.base.json`
- Build order is managed via workspace dependency graph
- Go agent has its own `go.mod` and is not part of the pnpm workspace
+22
View File
@@ -0,0 +1,22 @@
# ADR-002: TypeScript + Express for API
## Status
Accepted
## Context
The API server needs to be fast to develop, type-safe, and maintainable.
## Decision
Use TypeScript with Express.js, Drizzle ORM, and PostgreSQL.
## Rationale
- TypeScript provides end-to-end type safety when shared with the frontend
- Express is mature, well-documented, and sufficient for a REST API
- Drizzle ORM is lightweight, type-safe, and generates SQL directly
- Zod provides runtime request validation that aligns with TypeScript types
- bcrypt for password hashing, JWT for auth tokens
## Consequences
- API and web share the `@fleetforge/shared` package
- Drizzle migrations are SQL-based, version-controlled in `infrastructure/migrations/`
- No ORM overhead from heavier alternatives (Prisma, TypeORM)
+22
View File
@@ -0,0 +1,22 @@
# ADR-003: Go for Forge Agent
## Status
Accepted
## Context
The agent needs to run on Linux, Windows, and macOS with minimal dependencies and resource usage.
## Decision
Write the agent in Go, producing statically-linked binaries for each platform.
## Rationale
- Go compiles to a single binary with no runtime dependencies
- Excellent cross-compilation support (GOOS/GOARCH)
- Small memory footprint suitable for resource-constrained devices
- gopsutil library provides cross-platform system metrics
- Strong standard library for HTTP, JSON, and OS interaction
## Consequences
- Agent is built separately from the TypeScript monorepo
- Agent version is tracked in the source code and reported in heartbeats
- Future: could use Go plugins for platform-specific adapters
+24
View File
@@ -0,0 +1,24 @@
# ADR-004: Authentication Model
## Status
Accepted
## Context
The platform needs secure authentication for both admin users and device agents.
## Decision
- **Admin users**: JWT-based authentication with bcrypt password hashes
- **Device agents**: Unique credential per device, stored as SHA-256 hashes in the database
- **Enrollment**: Time-limited, optionally single-use tokens, also stored as hashes
## Rationale
- JWTs are stateless, simple to implement, and work well with REST APIs
- Device credentials are long-lived but can be rotated
- Token hashing prevents database compromise from revealing usable credentials
- Role-based authorization with hierarchy: owner > admin > operator > read_only
## Consequences
- JWT secret must be configured via environment variable
- Tokens should have reasonable expiry (24h default for users)
- Device credentials are generated during enrollment and stored securely
- All auth decisions are logged to the audit trail
+25
View File
@@ -0,0 +1,25 @@
# ADR-005: Device Status Calculation
## Status
Accepted
## Context
Devices report heartbeats at regular intervals. We need to determine online/offline status.
## Decision
- Agent sends heartbeats every 30 seconds (configurable)
- Server marks device as `online` on each received heartbeat
- A background worker checks for stale devices every 60 seconds
- If last heartbeat is older than 2 minutes, device is marked `offline`
- If metrics show concerning values (disk > 90%), device is marked `warning`
## Rationale
- Simple threshold-based status is reliable and easy to understand
- Status transitions are logged for audit purposes
- The threshold is configurable per-device or globally
- Future: more sophisticated health scoring
## Consequences
- Status is computed server-side, not trusted from the agent
- The heartbeat interval affects status responsiveness
- Status changes generate audit events and can trigger alerts