Projects / recap
Projects / Aros
active
9 sessions logged

Aros

One pane of glass for self-sovereign infrastructure — from bare metal to application, in a single browser tab.

The platform observes, acts — and now coheres. Cross-adapter correlation surfaced on every pane (click an IP, trace it; one machine reads as one entity), a consolidated Network section, a tamed top-level menu, and a follow-the-chain Approvals pipeline. Direction set by ADR-0032: GUI-driven estate onboarding — a connector registry, a tenant/site model, and removing the edge single-point-of-failure.

Current phase
Correlation & consolidation ✓

The platform observes, acts, and now reads as one coherent surface. End-to-end network visibility for any node (IP → switch → uplink → router → Traefik → Authentik → open ports), cross-adapter correlation surfaced on every pane and persisted at discovery, a single tabbed Network section, a de-sprawled top-level menu, and a follow-the-chain Approvals pipeline. Next, set by ADR-0032: a connector registry and multi-site onboarding.

Footprint
~30 infra VMs

dev/test/UAT app tiers, 3-node HA data tier, 4-node MinIO, observability + grafana tiers, edge + cache + frontend, meta — across pve1/pve2/pve3. Aros now discovers the full estate it lives on: ~46 VMs, 100+ containers, network devices, and the hardware beneath.

Data
HA Postgres proven

etcd + Patroni 4.x, 3-node, 2s failover via libpq multi-host. Validated at app layer, not just patronictl.

Source
4 repos

aros-docs · aros-infrastructure · aros-platform · aros-backend — Forgejo-hosted, Woodpecker-built.

Secrets
Vault-backed

Proxmox, TF AppRole, Forgejo, Woodpecker, PG-dev — KVv2 with per-service per-env layout.

The vision

One pane of glass

Aros is the operating system for self-sovereign infrastructure. One browser tab replaces twenty.

Today, operating a homelab estate means living across a dozen browser tabs — Proxmox for VMs, Portainer for containers, Unifi for networking, Vault for secrets, Grafana for metrics, PBS for backups, Traefik for routing, iDRAC for hardware, Cloudflare for DNS. Each tool is excellent at its job. None of them talk to each other. The operator is the integration layer, carrying context between tabs in their head.

Aros replaces that model. A single, tenant-aware control surface that absorbs every routine operation from every underlying tool — with better UX, a full audit trail, and the ability to hand routine work to AI agents under strict oversight.

The platform doesn’t replace the underlying tools; it wraps them behind adapter interfaces so the operator rarely needs to touch the native UIs for routine work. Proxmox, Unifi, iDRAC, Vault, PBS, Traefik, Cloudflare, ELK — they all become implementations of Aros capabilities, swappable without touching application code.

Architecture

What's built vs. where it's going

The platform is being constructed in layers. Each sprint adds a structural component that the next sprint builds on. Nothing decorative until the foundations are load-bearing.

PVE hosts
3

pve1, pve2, pve3

App-tier VMs (HA)
9

3 dev, 3 test, 3 UAT

Data-tier VMs (HA)
3

aros-pg-dev-1/2/3, etcd + Patroni

Discovered estate
46 VMs

plus 100+ containers, network devices, hardware — all correlated

Live fleet power
284W

Redfish per-host draw + inlet temp, charted over time

Adapters
11

proxmox · unifi · traefik · redfish · docker · domains + 5 health

Frontend tests
212

unit + e2e smoke, green every merge

Failover tested
2s

Patroni leader kill, zero dropped requests

The pipeline

From commit to production, through three environments

Every code change follows the same path: push to Forgejo, build via Woodpecker, auto-deploy to dev, manual promote through test and UAT. The pipeline was validated with the hello-world reference service and has since carried the real aros-backend modular monolith.

The development pipeline is the first piece of Aros infrastructure that had to work before any application code could land. It was designed to be boring and repeatable — the same flow whether deploying a health-check skeleton or a full domain module.

The flow: a git push to Forgejo triggers Woodpecker CI. The pipeline builds a multi-stage Docker image, pushes it to Forgejo’s built-in OCI registry, and SSH-deploys to the dev cluster (aros-dev-1/2/3 on pve2). Promotion to test and UAT is manual — a TARGET-gated trigger in the Woodpecker UI. Test VMs span pve1/pve2/pve3 for real HA validation. UAT mirrors test topology.

Every VM in the pipeline was provisioned via Terraform, hardened via Ansible, backed up via PBS, and has its credentials stored in Vault. No hand-built infrastructure anywhere in the chain.

High availability

Three nodes, zero single points of failure

HA isn't bolted on. Every tier that matters is distributed across three Proxmox hosts from day one.

The architecture mandates three-node minimum for every tier. The three PVE hosts (pve1, pve2, pve3) form a quorum-capable cluster. App-tier VMs are distributed one-per-host in test and UAT. The data tier runs a 3-node PostgreSQL cluster managed by Patroni with etcd for consensus.

The HA proof point: during Sprint 1 closeout, the Patroni leader was deliberately killed while a curl loop probed the application’s health endpoint every 2 seconds. The leader flipped from .231 to .233 inside one probe interval. Every probe returned 200. Zero “(no response)” lines in the captured window. libpq’s target_session_attrs=read-write found the new leader on the next reconnect without the application doing anything.

This same pattern extends forward. Redis will run Sentinel across three nodes. MinIO will run erasure-coded across three nodes. Traefik will run one instance per node. When the network tier gets its VLAN segmentation and dual-switch MLAG, even the switching fabric will have no single point of failure.

The ten pillars

What Aros will manage

The platform is structured as ten pillars — each independently navigable, each with its own data model and actions, all integrated through a common context model. Ask 'tell me everything about VM 102' and the answer draws from Infrastructure, Backup, Observability, Security, and Service Catalog.

Pillar 1
Infrastructure

The unified estate browser. Bare metal → hypervisors → VMs → containers → applications in a single navigable tree. VM lifecycle, container lifecycle, storage, networking, templates. Proxmox, UNRAID, Docker, Traefik, Unifi, iDRAC — all absorbed behind adapters.

Pillar 2
Identity & Access

Authentik-backed SSO across every managed service. Users, groups, tenants, roles, scopes. MFA, passkeys, API keys, service accounts. Federated identity. Session management. Every auth event audited.

Pillar 3
Observability

Prometheus + Thanos for metrics, ELK for logs, OpenTelemetry for traces. Native dashboards for the daily view; embedded Grafana for deep dives. Replaces Uptime Kuma with built-in synthetic monitoring.

Pillar 4
Operations

Terraform workspace management. Ansible playbook runner. Change management workflow. Runbook execution. Drift detection. The operator never runs terraform apply from a shell.

Pillar 5
Reliability

PBS integration, restic for offsite, restore drills on schedule, DR runbooks, health checks, SLO definition and tracking. Every protected resource has a verified, restorable backup.

Pillar 6
Security Operations

Vault for secrets, CrowdSec for IDS, Trivy for vuln scanning, Falco for runtime security, cert tracking, lateral movement detection, compliance posture. Security of the entire estate on one screen.

Pillar 7
Service Catalog

Every service: health, URL, owner, docs, dependencies, SLOs. Service dependency map. Deploy new instances from blueprints. Impact analysis before changes.

Pillar 8
Incident Management

Alert → incident → ticket → resolution → postmortem. Built in-house, not Jira. On-call schedule and routing. Status pages per tenant. MSP-ready customer comms.

Pillar 9
Knowledge

Greenfield wiki with WYSIWYG editor. ADRs, runbooks, API docs (auto-generated from OpenAPI), per-tenant knowledge spaces. Deep links from estate resources to relevant docs.

Pillar 10
Multi-tenancy & Federation

Tenant CRUD with whitelabel branding. Resource quotas. Edge nodes at remote sites. Buddy backup, MSP customer sites, cloud drift backup. Sites operate autonomously when central is unreachable.

Capability parity

Absorbing the tools you already use

Every underlying tool is being absorbed in tiers. Tier 1: native UX better than the tool itself. Tier 2: functional UX, equivalent. Tier 3: SSO-protected passthrough to the tool's own UI. Over time, Tier 2 flows into Tier 1, and Tier 3 shrinks.

Tier 1 targets (v1)
14

VM lifecycle, container lifecycle, backup jobs, Vault KV, Traefik routes, DNS records, alerts, power mgmt, …

Tier 2 targets (v1)
11

ZFS advanced, UNRAID array, Vault policies, Unifi VLAN, firewall rules, restore drills, …

Tier 3 targets (v1)
3

iDRAC BIOS, Unifi deep wireless, PVE cluster low-level

Tools absorbed
15

Proxmox, UNRAID, Docker, Portainer, Traefik, Unifi, iDRAC, Vault, PBS, Cloudflare, Grafana, Alertmanager, Uptime Kuma, ELK, CrowdSec

Adapter architecture

Swappable implementations, stable interfaces

Aros owns its abstractions. Underlying tools are adapters — implementations of capability interfaces. If Loki dies, the Logs adapter swaps to OpenObserve. If Authentik develops issues, the Identity adapter swaps to Zitadel. The application code never changes.

The adapter pattern is the architectural guarantee that Aros isn’t locked to any vendor or tool. Every external dependency sits behind a defined Python ABC (abstract base class) with capability declarations, health checks, and per-tenant configuration. The platform consumes adapters; it never consumes tools directly.

Concrete adapters in the v1 scope: Proxmox and UNRAID for Compute, ZFS and UNRAID and LVM for Storage, Unifi and Traefik and Cloudflare for Network, Authentik for Identity, Vault for Secrets, PBS and restic for Backup, ELK for Logs, Prometheus+Thanos for Metrics, CrowdSec for IDS, Trivy+Grype for Scanning, Falco for Runtime Security, Headscale for Mesh Networking.

Each adapter can be replaced independently. Each adapter declares its own sandboxing requirements. The same adapter interface that wraps Proxmox today could wrap a cloud hypervisor tomorrow — or a second homelab site across a Headscale mesh.

The data plane

What Aros manages

The managed estate — everything beneath Aros that the platform observes, controls, and reports on.

Compute
Bare metal → VM → container

PowerEdge servers via iDRAC for hardware health and power. Proxmox VE for virtualisation. Docker for containerised workloads. UNRAID KVM for NAS-resident VMs. Full lifecycle from provisioning to decommission, all in one tree view.

Storage
ZFS · UNRAID · LVM

Pool management, dataset CRUD, snapshot schedules, scrub monitoring. UNRAID array + parity + cache. LVM volumes. ~80TB usable across the estate.

Network
VLAN · Route · DNS · Firewall

Unifi for switching and VLANs. Traefik for reverse proxy and TLS. Cloudflare for DNS and edge. Firewall rules managed from Aros, not spread across three UIs.

Secrets
Vault-native

Every secret in KVv2, rotated, audited, scoped per tenant. Certificate tracking with expiry alerts. AppRole for machine identity. No secrets in environment variables or config files.

Agentic operations

AI writes the code, AI proposes the fix, the operator approves

Aros is built to be operated by humans and AI agents interchangeably — same API, same audit log, same approval flows.

The agentic model is tiered. Routine, low-risk operations can self-heal automatically — a container that crashes gets restarted, a failed backup gets retried, a certificate nearing expiry gets renewed. Higher-risk operations get proposed by an AI agent and presented to the operator for one-click approval. The operator sets the policy boundary per tenant, per pillar.

AI agents are first-class identities with their own scope, audit trail, and cost budget. Every action an agent takes is logged with the same fidelity as an operator action. The platform tracks token usage per agent and alerts on cost drift. Agents can be local (Ollama) or cloud (Anthropic, OpenAI), with a complexity-scored routing engine that sends simple tasks locally and reserves cloud models for harder reasoning.

The end state: the operator gets a morning briefing from Aros showing what happened overnight, what was auto-resolved, what needs attention, and what the AI is proposing. The operator reviews, approves, rejects, or adjusts — then goes about their day knowing the platform is watching.

Where we're going

The three-year end state

What Aros looks like when the platform matures — from the operator's daily experience to the MSP-ready multi-site deployment.

  1. Year 1

    Single-operator, single-site, full-stack visibility

    All ten pillars at Tier 1 or 2 parity. One browser tab for the entire estate. Aros replaces the vm-provisioner, Portainer, Uptime Kuma, and most Grafana usage. Authentik SSO across every managed service. WYSIWYG dashboard builder for custom views. Full audit trail for every action. AI proposes routine remediations via the change pipeline.
  2. Year 2

    Multi-tenant, multi-site, whitelabel-ready

    First non-system tenant onboarded. Whitelabel branding live. Buddy backup site federated via Headscale mesh. Edge nodes operating autonomously when central is unreachable. API consumed by external integrations (CLI, N8N, AI agents). Multi-tenant isolation verified. Cost tracking per tenant.
  3. Year 3

    MSP-capable, AI-native, self-managing

    Aros manages itself. AI agent proposes, tests, and promotes a production fix end-to-end. 10+ self-healing patterns in production with verified positive outcomes. MSP-ready: customer-facing surfaces, per-tenant billing data, SLA tracking, whitelabel deployment. Multi-site federation with cloud drift backup. The operator's only browser tab during 95% of operational work.
End state

What the operator's day looks like in three years

The concrete, daily experience that Aros is being built to deliver.

Open Aros in a single browser tab. The dashboard shows the entire estate: 4 bare metal servers, 30+ VMs, 100+ containers, network topology, storage pools, backup health, security posture, active incidents. Everything green, or the things that aren’t green are already being handled by the self-healing layer with an audit trail of what was done.

A morning briefing notification lists overnight events: two containers auto-restarted after OOM, a certificate was renewed 14 days before expiry, a Proxmox node ran a scheduled scrub and passed, a backup verification drill succeeded, an AI agent proposed a resource rebalance across the cluster (pending approval).

Click into Infrastructure and browse the estate tree: bare metal → hypervisor → VM → containers. Click a VM and see everything about it — CPU, memory, storage, network, backups, security scan results, dependencies, owner, runbooks, recent changes, active alerts — all from one view without switching tools.

Deploy a new service from a template: one click creates 3 VMs across 3 PVE hosts, installs the application stack via Ansible, configures Traefik routes, creates DNS records in Cloudflare, sets up monitoring, schedules backups, registers the service in the catalog, and posts to the changelog. The template parametrises everything the operator wants configurable and hardcodes everything they don’t.

When something breaks, the alert promotes to an incident with a timeline. The AI agent suggests a remediation based on similar past incidents. The operator reads the proposal, clicks approve, and the platform executes the fix through the same change pipeline that every other operation uses. The postmortem template is pre-filled with timeline, root cause candidates, and affected resources.

A tenant — a friend with a buddy-backup arrangement, or a future MSP client — sees their own branded view of the platform. Their own resources, their own users, their own SLOs, their own status page. They can’t see the operator’s resources or other tenants. They can request changes that route through an approval flow.

That’s the destination. Every sprint between now and then adds one more structural layer that makes the next layer possible.

Roadmap

The path so far, and what's next

The foundation sprints closed in roughly a week; then a process inflection traded sprint ceremony for autonomous runs. What follows is the real history and the queued work.

  1. Sprints 0–2

    Foundation: pipeline, HA Postgres, app skeleton, multi-tenancy + audit

    ~30 VMs via Terraform, hardened by Ansible, backed by PBS, secrets in Vault. FastAPI modular monolith on a 3-node Patroni cluster (2s failover, zero dropped requests). tenant_id + row-level security from day one. A hash-chained, tamper-evident audit log from the first migration.
  2. Sprints 3–4

    Tasks, approvals, platform health — then discovery + monitoring

    Dramatiq task framework, a policy + approval pipeline, tier-by-tier platform health. Then the adapter framework lands and Aros starts absorbing tools: Proxmox, UniFi, Traefik, Redfish, Docker, domains — discovering the estate into a containment hierarchy with cross-adapter correlation.
  3. The inflection

    Sprints → runs

    A failure analysis found the process drift (ceremony free to produce, expensive to read; statuses marking themselves; operator enthusiasm absent from the risk register). Sprint ceremony died; the RUN — one operator-authored prompt, ratifications up front, ship-gated priorities each with a demo — became the unit of planning. Six working agreements ratified.
  4. The runs

    The platform speaks, then deploys

    Health truth with reasons, a findings attention queue, platform/estate scope — then the ADR-0025 action framework live: Aros clones, configures, boots, and audit-chains its own VMs through a policy gate, human approval, and a single correlation chain from request to discovery.
  5. This stretch

    Correlation, consolidation, the Approvals pipeline

    End-to-end network visibility for any node; the cross-adapter thread surfaced everywhere and persisted at discovery; Network + UniFi merged into one section; the top-level menu de-sprawled; entity-detail tabs consolidated with zero information loss; a follow-the-chain Approvals pipeline; a genuine tenant-creation crash and six type-suppressions cleared.
  6. Next

    Correlation backbone + connector registry + edge HA

    ADR-0032, scoped and awaiting ratification: one normalized network-address table (consistent IPs, click-to-trace, route internals, hardware de-dup, and the resolver for east-west flows); a connector registry generalising the BMC pattern so any adapter is GUI-registered and Vault-backed — the unlock for multi-estate; and removing the edge single-point-of-failure, cheapest move first.
  7. The horizon

    Pillar build-out + multi-tenant, multi-site

    Storage, Backup, Security adapters; service catalog; incident management; a GUI-driven install that takes an operator from bare metal to a running, tenanted Aros; first non-system tenant; sites federated across a mesh. The ten-pillar end state.
Stack

What's in the box today

Hypervisor
Proxmox VE 8Ubuntu 24.04PBS
IaC
Terraformbpg/proxmoxAnsible
Secrets
HashiCorp VaultAppRole authKVv2 backend
CI/CD
Forgejo 9Woodpecker v3OCI registry
Data
PostgreSQL 16Patroni 4.xetcd 3.4libpq multi-host
Platform
FastAPISQLAlchemy 2.x asyncpsycopg3AlembicPython 3.12Docker 29
Edge
Traefik v3Cloudflare
Identity
Authentikoauth2-proxy
Frontend
React 18 + TSViteTanStack Router + QueryTailwind CSS
Cache / Queue
Redis 7Dramatiq
Object storage
MinIO
Observability
Prometheus + ThanosGrafana
Hardware
Redfish
Target stack

What's still coming as pillars land

Frontend
React 18+ TypeScriptViteTanStack QueryTailwind CSS
Identity
Authentikoauth2-proxyPasskeys / WebAuthn
Cache / Queue
Redis 7 + Sentinel
Task framework
Dramatiq
Object storage
MinIO
Search
Meilisearch
Metrics
Prometheus + Thanos
Logs
ELK
Traces
OpenTelemetry
IDS/IPS
CrowdSec
Scanning
Trivy + Grype
Runtime security
Falco
Mesh networking
Headscale
Local AI
Ollama
Orchestration
N8N
Design principle

Foundation over features

The painter spends 80% of their time on prep. Aros prioritises brickwork over decoration.

The sprint cadence is deliberately slow at the foundation layers. Sprint 0 built infrastructure. Sprint 1 built the application skeleton. Sprint 1.5 hardened the pipeline and secrets model. None of this is user-facing. None of it ships a feature. All of it means that when the first real domain module lands, it lands on a platform that’s reproducible, version-controlled, HA-tested, and pipeline-validated — not on a pile of shortcuts that need unwinding at scale.

The discipline extends to every architectural decision. Multi-tenancy is designed in at the schema level from day one, even with a single operator. Adapter interfaces are defined before the first adapter is written. The audit log is append-only and tamper-evident from the first migration. These choices cost time now and save rewrites later.

This is the deliberate opposite of “ship fast and fix it later.” When Aros reaches its first real user-facing feature, the runway beneath it will be three sprints long and battle-tested.

Session recaps

9 recaps logged

Deep-dive write-ups of specific build sessions — the chronology, the dead ends, the war stories.

  1. Post-Run-2 — correlation, consolidation, and the estate horizon Backend: network-path-from-any-node #40 · mapping-robustness #41. Frontend: thread-surface #31 · network-section #32 · detail-tab-consolidation #33 · nav-restructure #34 · approvals-pipeline #35 · schema-debt-cleanup #36. Docs: ADR-0032 (Proposed). Every PR CI-green and live-verified before the next started.

    Connecting the Dots

    The session that turned a platform which observes and acts into one that reads as a single coherent surface. It opened with the inventory hero — fleet summary, an Energy & Cooling tab pulling live per-host power and inlet temperature from Redfish, and a graph-integrity signal that finally says ok:true. Then the spine: end-to-end network visibility for any VM — IP → switch → uplink chain → router, the Traefik routes fronting it, whether Authentik gates it, and a read-only open-port probe — refactored so the same thread surfaces from a UniFi client, a switch, or the VM itself, and persisted at discovery time so it is cheap to show everywhere. A real-world collision (two genuinely distinct VMs both named private-client-services, both claiming 192.168.1.94) exposed three divergent IP-to-VM matchers; they were unified behind one rule that recovers a VM's MAC from its EUI-64 IPv6 and surfaces ambiguity rather than hiding it. On the front end: Network and UniFi merged into one tabbed section, the entity-detail tabs consolidated with zero information loss, the whole top-level menu de-sprawled (Health and Events removed, Cluster folded into Platform, Settings split into Environment / Preferences / Developer), and a full Approvals pipeline built — an Inbox pane of glass plus a follow-the-chain timeline reconstructed from the correlation id. A tech-debt pass fixed a genuine tenant-creation crash and cleared six type-suppressions. Finally the work lifted its head: a three-agent architecture review produced ADR-0032 (GUI-driven estate onboarding — a connector registry, a tenant/site model, an install state machine) and a dig into the edge node found the real risk the operator already suspected — aros-edge-1 runs ingress, forward-auth, and the identity provider on one VM, a single point of failure for logging in at all.

    correlationnetwork-identityinformation-architectureapprovalstech-debtspof-analysis
    Read recap
  2. Sprint 5 — the meta-story ADR-0031 ratified-as-amended 9f497b2 (after 11 days Proposed) · working agreements 8–13 in CLAUDE.md 133a269 · the validation evidence is the entire companion recap

    From Sprints to Runs — the Process Inflection

    The companion piece to The Platform Speaks, Then Deploys — the story of WHY those runs exist. Sprints 0 through 4 closed in roughly one week; Sprint 5 then sat open for 11+ days while its maintenance backlog grew faster than it closed and the operator did not touch the project for most of a week — his words: it felt like a chore. A commissioned failure analysis across all 30 ADRs, the build plan, and the ai-context corpus located the drift precisely: 300-to-500-word forensic backlog entries for sub-hour fixes; seven ADRs produced in 72 hours designing three sprints ahead, marked Accepted without a ratification trail; the one ADR explicitly gated on the operator sitting Proposed for 11 days while code shipped under it, violating the project's own 48-hour decision rule; and effort tracking available detail rather than stakes — the inventory data model got 650 lines of ADR while the remediation engine, the project's stated end goal, got 56. The fix, ratified 2026-06-10: sprint ceremony dead, the RUN as the unit of planning (one operator-authored prompt at the last responsible moment, ratifications up front, strictly ordered ship-gated priorities each with a demo, overflow capped at 3-line ledger entries), and working agreements 8 through 12 — proportional rigor, 3-line backlogs, status discipline, drift-flagging, and enthusiasm as a tracked resource. Agreement 13 followed two days later when the recap of the runs exposed the remaining gap: decisions made on the chat side of the wall must land in the repo as artifacts before the next run fires, because the repo light cone is all an autonomous run can see.

    processretrospectivefailure-analysisworking-agreementsrun-formatadr-discipline
    Read recap
  3. Sprint 5 long-runs (Run 1: make the platform speak · Run 2: Aros deploys · follow-ups: unified detail + apt visibility) backend main: 919b16d6 → 20a83312 (PRs #2–#14) · frontend main: 35d10ac6 (PRs #2–#14) · migrations 0013–0017 · evidence in aros-docs session-evidence/

    The Platform Speaks, Then Deploys

    Run 1 made the platform speak: corosync became the node-liveness authority (pve2/pve3 stopped lying), every non-healthy status carries machine+human reasons end to end, the inventory tree became containment-only with Estate/Services split, every entity gained a platform|estate scope, findings landed as the idempotent attention queue, the tenant switcher went real, and every remaining stub became honest about its gate. A polish pass then built real Hosts/VMs/Cluster/Findings pages and deleted every mock. Run 2 made the platform act: the ADR-0025 minimum slice went live — POST /api/v1/actions → policy gate (MSP vm.* → REQUIRE_APPROVAL) → approval → Dramatiq execution → audit, one correlation chain end to end. vm.deploy clones from the ubuntu-2404-cloud template into the ACL-fenced aros-deployed pool, writes server-authored provenance through the hypervisor, and discovery audit-links the new VM back onto the same chain — the detail page renders request → approval → execution → discovery as one timeline. M2 ran a 3-VM cluster as ONE ordered task with live per-member sub-states, halt-on-failure semantics (no rollback) backed by a P2 finding, and a deployed_group cluster entity with linker-resolved member chips. The follow-ups fixed the /infrastructure routes, rebuilt the entity detail page as a unified per-class view (resources, named topology, system identity), and lit up per-node pending apt updates behind a deliberately-scoped read grant — surfacing both real version drift across the PVE nodes (8.4.0 / 9.0.3 / 9.1.1) and 542 pending packages as live P4 findings.

    health-truthcorosyncreasons-contractcontainment-hierarchyscope-platform-estatefindings
    Read recap
  4. Sprint 4 cross-adapter linker: 6337694 · discovery defects fix: 1c29bee · frontend conventions: a1790f1 · grafana-pg patroni-raft: a464e66 · test-auth doc: b4a73c0 · Playwright smoke: e1732bb · integration on real PG: 3d91daa · migration single-head guard: 5b1d2ec · post-deploy smoke: cc8512c · CI iteration round 5: d623f12 · close-out verification: aa941a5

    Sprint 4 — Discovery, Notification Pipeline, and the CI Gate That Almost Was Not

    Sprint 4 gives Aros eyes. Migration 0010 lays down inventory.entity with FORCE RLS plus the platform tenant; 0011 seeds the MSP admin membership keyed on case-sensitive PLATFORM_ADMIN_*; 0012 lays down the notification alert + remediation_candidate tables. Two new discovery adapters (proxmox, docker_adapter) plus the cross-adapter linker that nests each docker container under the proxmox VM whose configured IP matches the container host (container then nests under VM nests under PVE node). Notification pipeline lands the four-stage dedup-correlate-severity-route pipeline with ntfy as the configurable terminal sink (no-op when unset). C3 observability cluster authored as 8 VMs distributed across the three physical PVE hosts per the ADR-0027 amendment that locked in the three-host failure-domain invariant; grafana-pg runs the postgres-patroni role in a raft variant (no external etcd, self-contained quorum). Frontend conventions (13-fc) and the test-auth strategy (14-test-auth) land as ai-context contracts. Then the close-out: a six-piece CI gate stream (test-auth, Playwright, integration on real PG, single-head migration guard, post-deploy smoke, deployment-template validation) plus a live discovery defect on dev (the 5-min interval was paused; the adapter docstring asserted a VM.Audit grant the live token does not actually have) plus a five-round CI integration iteration culminating in a dedicated non-superuser test role because PostgreSQL refuses to let the bootstrap superuser revoke its own SUPERUSER attribute. RLS audited adversarially over all seven tenant-scoped tables — t/t clean. Sprint 4 closes with the bar raised: a green PR has passed lint + types + unit + integration-on-real-PG + migration round-trip with single-head guard + Playwright E2E, and its deploy passes commit-match + synthetic create-and-read smoke.

    inventorydiscoverycross-adapter-linkerproxmox-adapternotification-pipelinededup-correlation
    Read recap
  5. Sprint 3 tasks: 9327f04 · policy + approvals: 7e4d58b · adapter zero + membership: 0e68576 · frontend swaps: c156495 · close-out adapter fixes: 3322963 · code splitting: 274aa54

    Sprint 3 — Tasks, Approvals, Adapter Zero, Platform Self-Awareness

    Sprint 3 makes the platform self-aware. Five built-in health adapters (patroni, redis, minio, backend, edge) feed GET /api/v1/platform/health with parallel-probe + 5s-per-adapter timeout, all built to the full ADR-0017 ABC so Sprint 4 extends them rather than rewriting. Two-layer policy engine (ADR-0018) with embedded condition-tree evaluator covers eleven operators; tenant CRUD now routes through policy_service.evaluate, returning 202 + ApprovalOut on REQUIRE_APPROVAL. Dramatiq + APScheduler split into three worker containers per env (tasks, discovery, seal) per ADR-0021. Four ADRs accepted (0017 adapters, 0018 policy, 0020 testing, 0021 workers). Four migrations (0006-0009). Close-out shipped five additional commits to fix four adapter bugs surfaced by the first real /platform/health probe, route-level code splitting via autoCodeSplitting on the router-plugin, the BusyBox-sh-quoting workers deploy bug (resolved with scripts/deploy-workers.sh shipped via scp + bash), and the Forgejo forward-auth + Woodpecker OAuth collision (operator-resolved by bypassing the gate on those paths). Metrics: 4 migrations, 5 adapters, 3 worker types, ~25 policy evaluator test cases, 140 pytest passing, initial frontend bundle 132 KB gzipped.

    adapter-frameworkpolicy-engineapprovalsdramatiqapschedulerpatroni-streaming
    Read recap
  6. Sprint 2 core.tenants: dcb4e39 · core.audit: 77d3744 · core.events: e85757a · seal: 826a4f5

    Sprint 2 — Audit Foundation, Multi-Tenant, Events, Seal

    Sprint 2 makes every state change auditable, every tenant isolated, every event deliverable, every seal tamper-evident. Five modules landed in one sprint: core.tenants (migration 0003 + middleware + RLS), core.audit (migration 0004 with partitioned audit.event + SHA-256 chain + chain_head pointer), core.events (Redis Streams via redis.asyncio), the watchdog + partition pre-create + seal background tasks (ADR-0010 asyncio loops with PG advisory-lock leader election), and migration 0005 (aros_seal_admin BYPASSRLS role per ADR-0016). Sprint 2 also shipped a CI migration guard (three-pass upgrade/downgrade/upgrade against a fresh PG 16) that caught three real type-cast bugs before they reached an operator. Eight ADRs accepted (0005, 0006, 0007, 0008, 0010, 0011, 0015 reserved, 0016). Operator-gated remaining work: alembic upgrade head 0005 on dev, env file rollout for SEAL_PG_PASSWORD + MINIO_*, promote to test + UAT, tag.

    multi-tenantrlsaudit-loghash-chainredis-streamsminio
    Read recap
  7. Sprint 1.5 1.5a: c2b1721 · 1.5b: f8e4a193

    Sprint 1.5 — Auth Foundation + Frontend Shell

    Sprint 1.5 brought the platform from headless-backend to logged-in-browser-app. Phase A stood up Authentik on aros-edge-1 with Microsoft Entra federation, wired oauth2-proxy + Traefik forward-auth in front of aros-dev/test/uat.ryanit.com, shipped aros-backend's auth middleware + identity module + migration 0002, and fixed Sprint 1's implicit shared-DB debt. Phase B scaffolded aros-frontend (Vite + React + TypeScript strict + TanStack Router + TanStack Query + shadcn-Radix + Tailwind), deployed via the same Woodpecker pattern as aros-backend, and surfaced one post-deploy bug (/api/docs returning 404 — FastAPI defaults vs Traefik routing). Five silent failures captured across both phases. Three ADRs accepted (0012 Authentik, 0013 edge topology, 0014 per-env Redis) plus ADR-0009 (frontend stack). Tags: sprint-1.5a-uat-green at aros-backend c2b1721, sprint-1.5b-uat-green at aros-frontend f8e4a19.

    authentikoauth2-proxytraefikforward-authoidcentra
    Read recap
  8. Sprint 1 570596d2d9

    Sprint 1 — First Real Application Code

    First real Aros application code deployed end-to-end. aros-backend scaffolded as a modular monolith — FastAPI, SQLAlchemy 2.x async over psycopg3 with libpq multi-host, ULID request IDs, Alembic migration, and /health/{live,ready,db}. Promoted dev → test → UAT under commit 570596d2d9, tagged sprint-1-uat-green. Three silent failures bit on the way: a Vault-stale Forgejo token without write:package, env-file perms locked to root when docker reads as hlvm, and a hello-decommission step that no-op'd because the wrong SSH user couldn't sudo non-interactively. Closed with a Patroni leader kill — zero dropped requests in the curl loop.

    fastapisqlalchemypsycopg3patronihaalembic
    Read recap
  9. Sprint 0 909ea5b

    Sprint 0 — bootstrap, end-to-end CI/CD, and an HA Postgres bonus

    End-to-end Sprint 0 closeout. 12 production VMs provisioned via Terraform, hardened via Ansible, glued together with Woodpecker CI/CD. Bonus round: 3-node HA PostgreSQL cluster on dedicated VMs, failover validated. One meta-tooling VM brought up to host this very page.

    terraformansiblewoodpeckerpatronietcdpostgresql
    Read recap