Operations-Dashboard v3 — Requirements

Problem Frame

Marvin hat keinen aggregierten Blick auf:

  • Was steht heute auf seinem Tisch — und was wartet auf andere
  • Wie ist die Burn-Rate (Cloud, SaaS, Belege)
  • Was passiert in welchem Projekt
  • Welche Belege sind noch nicht in Papierkram
  • Historische Entwicklung (Trends 2024/2025/2026) ueber alle Achsen

Daily-Briefing-Push deckt den Tag ab, ist aber linear/text. Marvin ist visueller Typ + ADHS — braucht Bilder, nicht Listen. Soll vom Handy unterwegs aufrufbar sein.

v2-Lineage: Plan v2 hatte ein Cloud-Backend (Lambda + EventBridge + S3-Daten) vorgesehen. Pivot am 2026-05-14: Backend wird verworfen. Begruendung: zusaetzlicher Always-On-Stack fuer Solo-User ohne Need. Stattdessen statischer Build + on-demand Backfill-Scripts. Snapshots leben im Vault.

v3 Requirements

Daten-Quellen (woher kommt was)

  • R1 Projekte: parse aus intern/projekte/*/_index.md Frontmatter via gray-matter in Next.js Server Components (src/lib/vault.ts). Keine zusaetzliche Aggregations-Schicht noetig — Schema 5.5 ist schon strukturiert.
  • R2 Kunden: parse aus intern/kunden/*.md Frontmatter. Verlinkung zu Projekten via customer:-Field.
  • R3 Finanzen aktuell: build-time-Pull via lokalem Script scripts/build-finanzen.ts aus gsuite-MCP (gleicher Pull wie heute, aber als pre-build statt Lambda). Output: ein JSON-File pro Build-Run in src/data/finanzen-current.json.
  • R4 Finanzen historisch: einmaliger scripts/backfill-finanzen.ts-Run dumpt Gmail-Belege 2024-2026 als monatliche Aggregat-Files nach intern/finanzen/snapshots/<jahr>-<monat>.json. Format: pro Monat Kategorien-Totals + Beleg-Count, KEINE Einzelpositionen (die bleiben in Papierkram / Gmail). Aggregate sind ausreichend fuer Trend-Charts.
  • R5 Cloud-Kosten aktuell: build-time-Pull via aws ce get-cost-and-usage + Hetzner-API + Cloudflare-API. Output: src/data/cloud-current.json.
  • R6 Cloud-Kosten historisch: einmaliger scripts/backfill-cloud.ts-Run dumpt 13 Monate Cost-Explorer-History als monatliche Snapshots nach intern/finanzen/cloud-snapshots/<jahr>-<monat>.json. Cost-Explorer-Retention ist 13 Monate — alles davor existiert nicht und wird nicht rekonstruiert.
  • R7 Activity-Stream (optional Phase 2): parse aus intern/runs/<jahr>-<monat>.md als Aktivitaeten-Log.

Frontend / Tech

  • R8 Next.js 16 + Tailwind v4 (bestehend in av-cockpit) + Recharts fuer Charts. Server Components lesen Vault-Daten, Client Components fuer interaktive Charts/Filter.
  • R9 Chart-Library: Recharts (direkt, bereits installiert in av-cockpit). Tremor explizit nicht (effektiv unmaintained seit Mitte 2024). Observable Plot als Optional-Add fuer eine spaetere Sankey/Force-Graph-Page.
  • R10 Typografie: Geist Sans (UI) + Geist Mono (Zahlen, Code), via geist-Package (self-contained, kein CDN).
  • R11 Aesthetik: Vercel/Stripe-Lane — viel Whitespace, shadow-as-border statt echte Borders, monochrom (#0d1117 fg, ffffff bg), Akzent 533afd nur fuer aktive Nav + CTAs. CSS Custom Properties (--color-*) statt Tailwind-Palette.
  • R12 Mobile-tauglich. Gleiche Funktionalitaet auf Desktop und Mobile (keine Lite-Variante). Charts shrinken, Cards stacken.

Customization

  • R13 Saved Views statt Drag-and-Drop. Drei vorbereitete Views als JSON in intern/firma/dashboard-views.json:
    • morning — was muss ich heute, Burn-Rate, Belege-Drift
    • cost-audit — alle Cloud-Charts, Burn-Trend, Provider-Verteilung
    • steuerberater — Belege-Listen, monatliche Aggregate, Pending-Pflege
  • R14 Pro Karte ein Show/Hide-Toggle, persistiert in localStorage (av-dashboard.hidden-cards.<view> Array von Card-IDs). Reorder via ↑↓-Buttons neben jeder Karte.
  • R15 Time-Range-Selektor (Tag / Monat / Quartal / Jahr / Custom). Globale Component, persistiert pro Page in localStorage.

Routing

  • R16 Bestehende Pages bleiben (/, /projekte, /cloud, /finanzen), erweitert um Drill-Down-Routes und Uebersicht:
    • / — „Heute” (Default Landing, 4 Bloecke wie unten)
    • /uebersicht — vollkundenanpassbare Wall mit allen verfuegbaren Cards + Saved-View-Switcher
    • /projekte und /projekte/<slug> — Liste + Detail
    • /cloud und /cloud/<account> — Kosten + Account-Drill
    • /finanzen und /finanzen/<jahr>/<monat> — Belege + Monatsdetail
    • /kunden/<slug> — Kunden-Profil mit verlinkten Projekten
    • /runs — Activity-Stream (Phase 2)

/heute v3 — vier Bloecke

  • R17 „Was muss ich tun” — Liste der ball_bei: mir-Projekte, sortiert nach next_step_due ASC, max 5 sichtbar
  • R18 „Aktive Projekte” — Karten-Grid, max 6 sichtbar (Rest hinter „weitere zeigen”), sortiert nach letzte_aktivitaet DESC, ball_bei-Color-Coding wie heute
  • R19 „Burn-Rate” — Cloud-Kosten letzte 30 Tage als Sparkline + grosse Zahl + ggf. Delta gegenueber Vormonat. Klick = /cloud
  • R20 „Belege-Drift” — Anzahl Belege noch nicht in Papierkram als Counter + Liste der Top-3-Urgent. Klick = /finanzen

Auth + Hosting

  • R21 Cognito + Google IdP, hello@-Konto only. Stub ist im Code (src/lib/auth.ts, Dashboard.astro) und wird in Phase 6 finalisiert.
  • R22 Hosting: S3 (eu-central-1, Frankfurt) + CloudFront. Aktivierung Cloudflare-DNS-Cutover auf dashboard.agenticventures.de in Phase 6.
  • R23 Keine US-CDN-Embeds. Fonts self-hosted, keine Google-Analytics, keine Cloudfront-Bootstrap.

Success Criteria

  • S1 /heute laedt in < 1s auf Desktop und Mobile, zeigt die vier Bloecke ohne Mock-Disclaimer
  • S2 Trend-Charts (Cloud, Finanzen) zeigen mindestens 6 Monate Historie (ab Backfill-Run)
  • S3 Marvin kann Karten auf /uebersicht ein-/ausblenden + reordern, persistiert ueber Page-Reload
  • S4 Saved Views switchbar in einem Click, Layout wechselt sofort
  • S5 Mobile-tauglich: alle Pages auf 375px-Viewport ohne horizontal Scroll, Charts shrinken sauber
  • S6 Live unter dashboard.agenticventures.de mit Cognito-Schutz (Google-Login hello@-only)

Scope Boundaries

Nicht im MVP:

  • Drag-and-Drop-Layout (kommt nur wenn Saved Views nach 3 Monaten nicht reichen)
  • Echtzeit-Updates / WebSocket / Server-Sent-Events (Build-time + manueller Refresh reichen)
  • Multi-User, Permission-Model, Steuerberater-Login
  • Auto-Trigger Backfill (Backfill ist on-demand-Script, Marvin laeuft es bei Bedarf manuell)
  • Echte historische Daten vor April 2025 fuer Cloud (Cost-Explorer-Retention-Limit)
  • Einzel-Beleg-Drilldown fuer Historie (Aggregat-Files only, Einzelpositionen in Papierkram)
  • Activity-Stream /runs (Phase 2)
  • Knowledge-Graph / Vault-Graph (gestrichen aus v2, kein klarer Use-Case fuer Solo)
  • Export (CSV/PDF) — data_origin-Source ist die Wahrheit

Explizit ausgeschlossen:

  • Kein Lambda, kein API-Server, keine DB
  • Keine US-Hosted-Drittanbieter im Frontend
  • Kein automatisches next_step-Auto-Fill (bleibt Marvins manuelle Pflege)

Key Decisions

  • Markdown-only ist Mittel, kein Selbstzweck. Build-Time-Scripts duerfen externe APIs ziehen, solange das Resultat im Vault als File landet. Reproduzierbarkeit + Git-Tracking sind das eigentliche Ziel.
  • Aggregat-Snapshots statt Einzel-Belegen. Pro Monat ein JSON, Kategorien-Totals + Counts. Einzel-Positionen leben in Papierkram. Pflegearm.
  • Saved Views statt Drag-and-Drop. Drei kuratierte Layouts decken Marvins Workflows ab. Reorder + Show/Hide reicht — kein dnd-kit, kein Library-Bloat.
  • Recharts direkt statt Tremor. Tremor ist effektiv unmaintained. Recharts bereits in av-cockpit installiert und auf /cloud im Einsatz (Area-Chart 7-Tage-Trend).
  • Cognito + Google bleibt. Stub ist da, Setup in Runbook v2 dokumentiert.
  • Bestehende Page-Struktur erweitert, nicht ersetzt. /heute /projekte /cloud /finanzen /routinen bleiben + Drill-Down-Routes + /uebersicht.
  • Geist Sans + Geist Mono via npm-Package. Self-contained, DSGVO-konform, kein CDN.
  • [NEU 2026-05-16] av-cockpit ersetzt av-dashboard. Next.js 16 statt Astro 5. Vault-Bridge src/lib/vault.ts liest Frontmatter direkt via gray-matter + fs in Server Components. Kein Content-Collections-Setup noetig. Static Export (next buildout/) nach S3. Deploy-Script scripts/deploy.sh synct nach S3 + CloudFront-Invalidation.

Dependencies / Assumptions

  • AWS Cost Explorer API zugaenglich aus av-mgmt-Account fuer alle Linked-Accounts (Cross-Account-Cost-Aggregation aktiviert).
  • Hetzner-API-Token + Cloudflare-API-Token verfuegbar (.env.local im av-cockpit Repo).
  • Gmail-Belege-Label Belege ist konsistent gepflegt (Marvin labelt eingehende Belege).
  • Projekt-Frontmatter Schema 5.5 ist im Vault konsistent (alle aktiven Projekte haben status, customer, next_step, ball_bei).
  • Cognito User-Pool + Google-IdP-Config existiert in av-production (siehe Runbook v2).
  • av-cockpit Repo (~/source/av-cockpit/) ist aktuelles Code-Repo. av-dashboard (Astro) ist Vorgaenger und liegt noch in ~/source/av-dashboard/ als Referenz.

Outstanding Questions

Resolve Before Implementation

Keine.

Deferred to Build-Time

  • [Affects R4] Wie genau parsen wir Belege-Mails fuer Kategorisierung? Heutige data_origin: gmail-mcp (hello@ Gmail-Label-Belege + From-Filter) ist Vorbild — Script muss From:-Sender-Pattern matchen gegen Kategorie-Liste aus intern/finanzen/beleg-quellen.md.
  • [Affects R6] Hetzner historische Kosten — API gibt nur aktuelle laufende Periode. Backfill ist auf AWS-Daten beschraenkt, Hetzner laeuft ab heute „live”.
  • [Affects R14] Wie verhalten sich localStorage-Praeferenzen bei Saved-View-Switch? Pro View eigene Praefs oder global?
  • [Affects R20] Belege-Drift soll auch faellige Pending-Items zeigen — Datenformat im Finanzen-Snapshot dafuer?

Was gebaut ist (Stand 2026-05-17)

Lambda-Infrastruktur (agents-platform)

DashboardStack (3x taeglich, 9:00/13:00/18:00 UTC):

  • AWS-Kosten via Cost Explorer → aws-costs.json

LiveRefreshStack (alle 10 Minuten):

  • github_activity.pyrepo-health.json
  • routines.py (CloudWatch-Logs-Parse) → routines-status.json
  • email_triage.py (Gmail readonly + Bedrock Haiku 4.5 EU) → email-triage.json
  • Kalender-Stub → calendar-<datum>.json

Alle JSON-Files landen im DataBucket av-dashboard-data-425924867359 unter api/data/.

Sicherheits-Design Email-Triage:

  • Gmail-OAuth nur gmail.readonly — kein Write aus Lambda
  • Draft-Text nur als String in JSON, nie in Gmail gespeichert
  • Marvin erstellt Drafts manuell via Cockpit oder gsuite-MCP

Frontend (av-cockpit)

Pages: /heute, /projekte, /infra (Cloud-Kosten + Routinen), /email, /finanzen
Sidebar: Heute / Projekte / Infra / Email / Finanzen
SWR: revalidateOnFocus: true only, kein refreshInterval (Lambda laeuft ohnehin nur 3x/10Min)

Email-Page /email:

  • Relevante Mails: Importance-Badge + Bedrock-Einschaetzung + aufklappbarer Draft-Text + Copy-Button
  • Ignorierte Mails: einklappbare Liste
  • Meta-Zeile: total / gefiltert / klassifiziert

Finanzen-Page /finanzen (Phase 1, 2026-05-17):

  • Forderungen offen: parsed ## Offene Forderungen-Tabellen aus intern/kunden/*.md, sortiert nach Faelligkeit, Summe + Ueberfaellig-Highlight
  • Zu stellen: Posten mit Status zu stellen, gruppiert nach Kunde, Blocker-Hinweis (z.B. „wartet HR-Eintragung”)
  • Qonto-Slots: 3 Karten (Kontostand / Eingaenge 30d / Ausgaben Top 3) im Disabled-State, Hook useQontoData() ist API-kompatibel zum spaeteren qonto.json
  • Ausgaben-Trend: Empty-State („Trend-Daten kommen mit Qonto”), echte Daten kommen via intern/finanzen/snapshots/<jahr>-<monat>.json
  • Sidebar: neue „Outstanding”-Linie unter Pipeline-Block, zeigt offene Forderungen-Summe (klickbar → /finanzen)
  • Plan: 2026-05-17-001-feat-finanzen-page-plan.md

Deployment

# Vollstaendiger Deploy inkl. Vault-Kontext-Upload:
./scripts/deploy.sh
 
# generate-context.mjs allein (wenn Projekte/Kunden sich geaendert haben):
node scripts/generate-context.mjs --upload

Offene Baustellen

  1. generate-context.mjs einmal mit --upload laufen lassen — dann hat Bedrock Projekt-Kontext fuer Email-Klassifikation (aktuell leerer Kontext, weil das File noch nicht in S3 liegt)
  2. Projekt-Detail-Route /projekte/[slug] — Prototype unter assets/prototypen/bas-twin-overview.html
  3. Vault-Bridge erweitern (src/lib/vault.ts) — loadProject(slug) mit Pipeline-Stages fuer Detail-Route
  4. Qonto-MCP + Snapshot-Lambda — wartet HR-Eintragung. Eigenbau mcp-qonto (FastMCP, gleicher Pattern wie mcp-papierkram) + Lambda qonto-snapshot in agents-platform (alle 10 Min) → qonto.json in DataBucket. useQontoData-Hook ist schon da, Slots in /finanzen warten nur auf die Datenquelle.
  5. Becker + Icking Forderungen ergaenzen — heute nicht in /finanzen weil Vertrag nicht unterschrieben (Becker) bzw. komplett Pipeline-Stage (Icking HeyJulia v4 wartet auf Antwort). Sobald Meilenstein-Rechnungen anstehen: Tabelle ## Offene Forderungen in den jeweiligen Kunden-Files anlegen.
  6. Kalender-Integration — Google Calendar Service Account + Delegation statt Stub