Monolith

The monolith is the FastAPI + SvelteKit application suite behind most of this homelab. It combines a personal knowledge graph, a Discord chat agent, the EmberVM-backed software factory, and small apps (including Grimoire, hikes, trips, stars, and ships) over a shared Postgres data plane. Separate private, public, and agent compositions ship only the routes and code each audience needs; jomcgi.dev is the public surface.

Architecture

The backend is a FastAPI app (app/main.py) organized into domains, one directory per feature area, each owning its own routes, models, and tests colocated as *_test.py files next to the code they cover. Domains talk to a shared Postgres database (shared/) through SQLModel, and a Postgres-backed scheduler (scheduler/) drives background jobs (ingest, retention, digests, backfills) without a separate workflow engine.

The frontend is a SvelteKit app (frontend/) that renders both the public website and the private app surfaces. Public routes proxy to the backend's public API through +page.server.js loaders so pages render server-side and stay cacheable at the edge; private routes talk to the authenticated API.

The deployed application has distinct audience surfaces:

  • Public tier: read-only, unauthenticated routes served at jomcgi.dev (health, public apps, docs, and published factory and knowledge views). It is a pruned binary on the restricted public_reader role, with a narrowly scoped writer for Grimoire chat.
  • Private tier: authenticated apps, APIs, Discord integration, knowledge editing, and factory controls behind the private ingress.
  • Agent tier: a separate pruned MCP server for EmberVM guests. It exposes the bounded knowledge and Kubernetes observation tools described in ARCHITECTURE.md, not the private catalogue.
  • Friends surface: the moving planner and Grimoire campaign lobby, each protected by its own Authentik policy. Grimoire supports invitation-only account registration, campaign ownership, and player invitations.

The obsolete DR jobs and Canada Campsites frontend pages are retired. Their former /app/dr-jobs and /app/campsites URLs use the standard path-aware 404 page, including saved filter links. The backend domains, records, refresh jobs and backups remain available independently. The retained DR jobs digest still includes its former page link, which now resolves to that 404.

The retired private Firecracker and Qwen demo pages, the Semgrep performance dashboard, the Semgrep MCP tool and the public Semgrep exhibit are not part of any tier. Public EmberVM pages and their probes remain independent. The committed Firecracker story measurements and Qwen replay remain published. Their captures depended on the retired private demos API and the removed SigNoz span store and cannot be regenerated. The Qwen capture scripts are removed.

The tier boundaries are enforced through separate compositions, database roles, and ingress policy; see ARCHITECTURE.md sections 1 to 3. The hazard model for this boundary is STPA.md.

The shipped Factory selects bounded issue work, asks a per-task Planner to build a DAG, and has an Executor run its role-specific nodes. Legacy factory_conductor names refer to that task planner, not to the proposed operator-facing Conductor. The maintained role and record contract specifies the top-level Conductor without presenting it as shipped. The expanded MCP review and steering interface remains follow-up work in #5788.

Trust and safety

Discord engagement runs behind a per-server, per-user trust ledger. Narrow regex heuristics, an asynchronous LLM intent classifier, and a shadow-first random forest feed one score. The thresholds are environment-overridable; a pardon restores the score and relabels recent events, so a wrong lockout becomes corrective training data. Current state: ARCHITECTURE.md.

Key subdirectories

Path What it is
app/ FastAPI entrypoint, app wiring, lifespan, logging, OpenTelemetry setup
frontend/ SvelteKit app: public website, private app UIs
chart/ Helm chart for the service (templates, migrations, dashboards)
deploy/ ArgoCD Application, Helm values, and GitOps wiring for this cluster
knowledge/ Evidence ingestion, extraction, retrieval, public views, and knowledge interventions
chat/ Discord bot, trust and safety, triggers, reminders, summaries, and session adapter
factory/ Factory execution, task planning, DAG orchestration, operator controls, and public snapshots
scheduler/ Postgres-backed job scheduler shared by all domains
shared/ Cross-domain database session/engine setup and test helpers
grimoire/, hikes/, ships/, stars/, trips/, worldcup/ Individual apps, each with its own routes and models
campsites/, dr_jobs/ Retained backend APIs, data models and jobs; frontend pages retired
e2e/ End-to-end tests spanning the frontend and backend together

Deployment

The monolith is packaged as a Helm chart (chart/) and published as an OCI artifact. Images are built amd64-only with apko in CI. A merge to main publishes the chart and writes its new version back to the repository. Production runs on the GKE hub, where Kargo promotes new chart versions to the monolith and monolith-public ArgoCD Applications. The home deployment was retired in #6914; deploy/application.yaml remains only as publication metadata for chart-version write-back. See Platform architecture: GitOps and delivery for the current pipeline.

Database schema changes go through Atlas migrations checked in under chart/migrations/, applied by an in-cluster Atlas operator rather than at application startup.

Public Ember exhibits use the recorded Firecracker restore replay. The live Postgres and Bazel demo front doors, their code (ember_public keeps only the agent-lane probes) and their combined synthetic schedule are retired. Public notes provide graph browsing; the notes chat (chat_public, now only its retention jobs) is retired and the homepage points visitors to the factory activity visuals. Production agent lane probes remain on the private tier.