Zum Hauptinhalt
Zurück zu Projekten
Ops Panel logo

Ops Panel

Internes System

Architekturdiagramm des Ops Panel Ops Panel 24 projenin durumu tek tabloda — tarama panelin dışında koşar Proje adları bu şemada maskelidir. Panel teşhis eder; düzeltmeyi ilgili repoda ben yaparım. ZAMANLAYICI GitHub Actions toplu tarama burada koşar sıklık sınırı ve zaman aşımı yok servis hesabı anahtarları Actions secret'larında Tarayıcı script domain ve SSL bitişi dağıtım durumu arama ve ölçüm bağlantıları 24 proje × birden çok çağrı Neon Postgres 9 tablo · 7 migration envanter · tarama · bulgu · öneri · görev bulgunun ne zamandan beri açık olduğu geçmişten okunur Panel — yalnız okur ve gösterir 11 sayfa: envanter, taramalar, bulgular, öneriler, görevler, yönetim proje-01 proje-02 proje-03 … proje-24 Panel kod değiştirmez, repo okumaz, sayfa yüklenirken canlı veri çekmez. Panel tarafındaki secret Yalnız tek proje için "şimdi tara". Toplu taramanın anahtarları buraya hiç girmez. Sızma yüzeyi ikiye bölünmüş olur. Neden iki ayrı secret kümesi Barındırma planı zamanlayıcıyı günde bir çalışmaya ve fonksiyonu on saniyeye sınırlıyor; 24 projelik toplu tarama bu sürede bitmiyor. Tarama dışarı taşınınca geniş yetkili anahtarlar da dışarıda kaldı: panelin ortamında yalnız tek proje sorgulayacak kadar yetki var. Bedeli, aynı anahtarın iki yerde yönetilmesi ve birinin unutulabilmesi. Ekranda görünen alan adları, trafik sayıları, kayıt firması ve DNS haritası bu görselde bilerek yer almıyor.
Der Status von 24 Projekten in einer Tabelle. Der Sammelscan läuft außerhalb des Panels in GitHub Actions; weitreichende Dienstkonto-Schlüssel liegen ausschließlich in den Actions-Secrets. Ergebnisse werden in neun Tabellen auf Neon Postgres geschrieben, die 11 Seiten des Panels lesen diese Daten nur — es ändert keinen Code, liest kein Repository und holt beim Seitenaufbau keine Live-Daten. Das eigene Secret des Panels erlaubt nur ein „jetzt scannen“ für ein einzelnes Projekt.

Ein internes Kontrollpanel, das die 24 von mir betreuten Projekte in einer Tabelle überwacht. Domain- und Zertifikatsablauf, Deployment-Status sowie Lücken bei Such- und Messanbindungen liegen an einer Stelle. Das Panel ändert keinen Code; es stellt fest, und die Korrektur mache ich im Repository des jeweiligen Projekts.

Verwendete Technologien

  • Next.js 16
  • TypeScript
  • Drizzle ORM
  • Neon Postgres
  • Auth.js
  • GitHub Actions
  • Web Push (VAPID)

Hauptmerkmale

  • Der Zustand von 24 Projekten in einer Tabelle — Inventar, Scans, Befunde, Empfehlungen und Aufgaben
  • Der Sammel-Scan läuft außerhalb des Panels, als geplanter Job
  • Das Panel ändert keinen Code, liest keine Repositories, holt beim Seitenaufbau keine Live-Daten
  • Wie lange ein Befund offen ist, wird aus der Historie gelesen
  • Weitreichende Schlüssel gelangen nie in die Umgebung des Panels
  • Zu jedem Befund gibt es ein kopierbares Korrekturkommando

Entwicklungszeit

1,5 Monate

Problem

Wer vierundzwanzig getrennte Projekte und Domains betreut, verliert nicht den Code, sondern die Sichtbarkeit. Ein Zertifikat läuft ab, ein Deployment ist fehlgeschlagen und geblieben, auf einer Website wurde die Messung nie eingerichtet — nichts davon erscheint als Fehler; eines Tages fällt es jemandem einfach auf. Der eigentliche Teil des Problems ist nicht die Erkennung, sondern die Dauer: Ohne zu wissen, seit wann eine Lücke besteht, lässt sich nicht entscheiden, welche zuerst geschlossen wird. Der zweite Punkt: Das Überwachungswerkzeug ist selbst eine Risikoquelle — ein Schlüsselsatz, der vierundzwanzig Projekte erreicht, rückt die Frage, wo diese Schlüssel liegen, ins Zentrum des Entwurfs.

Nutzer

Ein Nutzer: ich. Das ist eine Randbedingung, die das Panel geformt hat — weder Mehrbenutzer-Berechtigungen noch Einladungsablauf oder Rollenverwaltung wurden geschrieben. Es gibt jedoch zwei Nutzungsmomente: den Blick am Morgen (was ist heute kaputt) und den Blick in der Woche (welche Lücke besteht am längsten). Danach ist das Panel aufgeteilt.

Meine Rolle

Einzelner Entwickler. Die Analyse der Randbedingungen, Datenmodell, Scan-Skript, Panel-Oberfläche, Benachrichtigungsschicht und Bereitstellung.

Architektur

Das System ist zweigeteilt, und diese Teilung ist das Zentrum des Entwurfs. Der Sammel-Scan läuft nicht in der Umgebung des Panels, sondern außerhalb als geplanter Job: Er fragt vierundzwanzig Projekte nacheinander ab und schreibt das Ergebnis direkt in Neon Postgres. Das Panel liest nur. Beim Seitenaufbau geht keine Anfrage an einen externen Dienst; alles auf dem Bildschirm ist ein zuvor geschriebenes Scan-Ergebnis. Das Datenmodell ruht auf fünf Begriffen: das Projekt im Inventar, ein Scan-Lauf und ein einzelner Scan, der aus einem Scan entstehende Befund, die daraus abgeleitete Empfehlung und die daraus entschiedene Aufgabe. Da Änderungen in ein eigenes Protokoll geschrieben werden, lässt sich aus der Historie ablesen, wann ein Befund entstand und wie lange er besteht. Zeigt das Panel einen Befund, stellt es ein kopierbares Kommando daneben; ausgeführt wird es in meinem Terminal, nicht im Panel.

Zentrale Entscheidungen

  1. Der Sammel-Scan läuft nicht in der Umgebung des Panels

    Zwei harte Randbedingungen führten dazu. Erstens der Planer: Im genutzten Hosting-Tarif läuft ein geplanter Job höchstens einmal täglich und der Auslösezeitpunkt ist unbestimmt. Zweitens die Dauer: Im selben Tarif liegt das Funktions-Timeout bei zehn Sekunden, und ein Scan über vierundzwanzig Projekte wird darin nicht fertig. Das Auslagern des Scans beseitigte beides — keine Frequenzgrenze, kein Timeout.

    KompromissDas System lebt nun in zwei Umgebungen, und beide Konfigurationen müssen gemeinsam stimmen. Ein Fehler auf der Scan-Seite erscheint im Panel nicht als Fehler; die Daten sind schlicht nicht aktualisiert, und um das zu bemerken, muss man die Scan-Läufe selbst ansehen.

  2. Weitreichende Schlüssel gelangen nie in die Umgebung des Panels

    Die Teilung entstand aus der Planer-Randbedingung, ihr eigentlicher Wert liegt aber in der Sicherheit: Der Schlüsselsatz, der vierundzwanzig Projekte erreicht, liegt dort, wo der Scan läuft; die Umgebung des Panels trägt nur so viel Berechtigung, wie für die Abfrage eines einzelnen Projekts nötig ist. Eine Kompromittierung des Panels bedeutet keinen Zugriff auf das gesamte Portfolio.

    KompromissDerselbe Schlüssel wird an zwei Stellen verwaltet, und wird einer rotiert, kann der andere vergessen werden. Eine automatische Prüfung dafür gibt es nicht; die vergessene Seite zeigt sich erst, wenn die zugehörige Funktion ausfällt.

  3. Das Panel stellt fest; es ändert keinen Code

    Das Panel ist eine bereitgestellte Anwendung; es erreicht kein lokales Dateisystem und liest keine Repositories. Statt diese Randbedingung zu umgehen, wurde der Umfang danach gezogen: Das Panel zeigt das Problem samt Kontext, stellt ein kopierbares Kommando daneben, und die Korrektur mache ich in meinem eigenen Terminal. Ein Werkzeug, das automatische Korrekturen schreibt, müsste in vierundzwanzig verschiedenen Codebasen mit denselben Annahmen arbeiten.

    KompromissDer Korrekturschritt ist nicht automatisiert; das Panel kann sagen, dass etwas kaputt ist, sieht die Behebung aber erst beim nächsten Scan. Bis dahin bleibt derselbe Befund auf dem Bildschirm.

  4. Maskierte Projektnamen statt echter Domains auf dem Bildschirm

    Das Inventar des Panels enthält Domainnamen, Registrar- und DNS-Angaben, Verkehrszahlen und Kontaktdaten. Diese gehören der Kundschaft; ein in einem Portfolio gezeigtes Bild darf sie nicht tragen. In dieser Fallstudie erscheinen die Projekte mit nummerierten Bezeichnern.

    KompromissDie Maskierung schwächt den Eindruck realer Nutzung: Der Screenshot erklärt, was das System tut, zeigt aber nicht, was eine Nutzerin sieht. Dieser Preis wird bewusst gezahlt.

Technologiewahl

Auf der Panel-Seite Next.js und Drizzle, auf der Scan-Seite ein schlichtes Node-Skript — beide teilen dasselbe Schema, denn die einzige Quelle der Wahrheit ist die Datenbank. Neon läuft im selben serverlosen Modell wie die Bereitstellung und ist auch vom extern laufenden Scan-Job erreichbar; eine zweite Kopie des Inventars gibt es nicht. Eine CI-Pipeline als Planer zu nutzen, ist keine Vorliebe, sondern Randbedingung: Sie war die einzige Option ohne Frequenz- und Zeitgrenze. Da es nur eine Person gibt, wurde kein aufwendiges Berechtigungsmodell gebaut. Web Push verkürzt die Zeit, bis ein Befund bemerkt wird — eine im Postfach verlorene Warnung ist keine Warnung.

Sicherheit

Das Panel ist sitzungsgeschützt, und der Routenschutz läuft in der Node-Laufzeit. Sensible Inventarfelder — Registrar, DNS-Konfiguration, Kontaktdaten — sind nur im Panel sichtbar und gelangen in keine externe Ausgabe, keinen Screenshot und nicht in diese Fallstudie. Weitreichende Dienstkonto-Schlüssel liegen nicht in der Umgebung des Panels; dort besteht nur so viel Berechtigung, wie für die Abfrage eines einzelnen Projekts nötig ist. Die Berechtigungen der Dienstkonten werden je Property von Hand erteilt — automatisieren lässt sich das nicht, was zugleich verhindert, dass Berechtigungen still wachsen.

Performance

Dieses Panel ist ein geschlossenes System; da keine mit Datum versehene Lighthouse-Ausgabe vorliegt, steht hier kein Seitengeschwindigkeits-Score. Das strukturelle Maß lautet: Beim Seitenaufbau geht keine Anfrage an einen externen Dienst, jeder Wert auf dem Bildschirm wird aus der Datenbank gelesen. Da ein Scan über vierundzwanzig Projekte nicht in ein Zehn-Sekunden-Timeout passte, wurde er aus dem Panel ausgelagert; der einzige verbliebene Scan-Pfad im Panel ist der "jetzt scannen"-Endpunkt für ein einzelnes Projekt, gemessen in Sekunden.

Ergebnisse

Aktive Entwicklung
2026-07 → 2026-08 · 47 Commits
TypeScript-Quelldateien
87
Testdateien
11
Schema
9 Tabellen · 7 Migrationen — Projekt, Scan, Scan-Lauf, Befund, Empfehlung, Aufgabe, Änderungsprotokoll
Überwachungsumfang
24 Projekte in einem Inventar; eine zweite Kopie des Inventars gibt es nicht
Routen
11 Seiten
Architekturgarantie
Das Panel schreibt nicht: kein Code, keine Repositories, keine Live-Daten beim Seitenaufbau
Architekturgarantie
Die weitreichenden Schlüssel des Sammel-Scans liegen nicht in der Umgebung des Panels

Was ich heute anders machen würde

Ursprünglich hielt ich das Inventar als YAML-Dateien im Repository und hatte geschrieben, ich würde es nicht in eine Datenbank verlagern; dann habe ich es verlagert und die YAML-Seite vollständig gelöscht. Richtig finde ich nicht die Verlagerung, sondern die Löschung: Existieren zwei Kopien derselben Information, wird irgendwann strittig, welche stimmt. Dieselbe Lehre kam aus Bergaz Operations — dort steht dieselbe Person, weil vier getrennte Systeme eigene Datensätze führen, an zwei Stellen als zwei Einträge, und die Zuordnung geschieht von Hand. Der zweite Punkt ist die Scan-Seite: Heute würde ich den Scan seine eigene Gesundheit ebenfalls in die Datenbank schreiben lassen. Derzeit unterscheidet das Panel nicht zwischen "es gibt Daten" und "die Daten sind aktuell"; ein fehlgeschlagener Scan-Lauf lässt alte Daten still korrekt aussehen.

Internes System

Finden wir gemeinsam den richtigen Einstieg

Sagen Sie mir, was Sie bauen möchten; ich sage Ihnen vorab, wie lange es dauert und was der sinnvolle erste Schritt ist.