Feature Chain — den gesamten Stack mit einer einzigen operationId verfolgen

Welche Dateien müssen geändert werden, um ein Feature anzupassen? Gib eine operationId ein — und du hast die Antwort.


Das Problem

In einer Fullstack-Anwendung steckt „ein Feature" nie in einer einzigen Datei.

Nehmen wir an, das Feature „Angebot annehmen (AcceptProposal)" soll geändert werden. Es ist im API-Spec vorhanden, in der Service-Logik, im Datenbankschema, in der Autorisierungsrichtlinie, im Zustandsübergangsdiagramm, in externen Funktionsaufrufen, in Testszenarien und im Frontend.

Bisher gab es zwei Methoden, um diesen Gesamtumfang zu erfassen:

  1. Grep dutzende Male ausführen
  2. Den Code manuell durchverfolgen

Beide Ansätze sind langsam, und bei beiden entstehen Lücken. Besonders die schichtübergreifenden Referenzen — vom API-Spec zum Service, vom Service zum DB-Schema, vom Service zur Autorisierungsrichtlinie — lassen sich in der Praxis kaum vollständig manuell nachverfolgen.

Wenn jedoch jede Schicht die anderen symbolisch referenziert, genügt es, diesen Referenzen zu folgen, um den gesamten Umfang automatisch sichtbar zu machen.


Was ist Feature Chain?

Feature Chain extrahiert alle Source-Knoten, die mit einem einzigen API-Feature (operationId) verbunden sind.

Ausgehend von einer operationId als Startpunkt folgt es den symbolischen Referenzen zwischen den Quellen und gibt alle zugehörigen Dateien mit Zeilennummern auf einmal aus. Dutzende Grep-Aufrufe werden durch einen einzigen Befehl ersetzt.

fullend chain AcceptProposal specs/
── Feature Chain: AcceptProposal ──

  OpenAPI    api/openapi.yaml:296                          POST /proposals/{id}/accept
  SSaC       service/proposal/accept_proposal.ssac:19      @get @empty @auth @state @put @call @post @response
  DDL        db/gigs.sql:1                                 CREATE TABLE gigs
  DDL        db/proposals.sql:1                            CREATE TABLE proposals
  DDL        db/transactions.sql:1                         CREATE TABLE transactions
  Rego       policy/authz.rego:3                           resource: gig
  StateDiag  states/gig.md:7                               diagram: gig → AcceptProposal
  StateDiag  states/proposal.md:6                          diagram: proposal → AcceptProposal
  FuncSpec   func/billing/hold_escrow.go:8                 @func billing.HoldEscrow
  Gherkin    scenario/gig_lifecycle.feature:4              Scenario: Happy Path - Full Gig Lifecycle
  Gherkin    scenario/gig_lifecycle.feature:42             Scenario: Unauthorized Access

Die gesamte Struktur eines Features ist auf einem Bildschirm sichtbar. Nicht verbundene Schichten werden nicht ausgegeben.


Warum ist das möglich?

Das ist kein Zaubertrick. Es funktioniert, weil die Quellen einander bereits referenzieren.

Im fullend-Framework verweist jede SSOT (Single Source of Truth)-Schicht symbolisch auf andere Schichten:

  • SSaC’s @get Model.Method → DDL-Tabelle
  • SSaC’s @auth action resource → Rego-Autorisierungsrichtlinie
  • SSaC’s @state diagramID → Mermaid-Zustandsdiagramm
  • SSaC’s @call pkg.Func → Func Spec-Implementierung
  • OpenAPI’s operationId → SSaC-Dateiname
  • Gherkin’s Action-Schritt → operationId
  • STML’s Endpoint → OpenAPI-Pfad

Diese Referenzen wurden ursprünglich für crosscheck entwickelt — ein Werkzeug zur Validierung der Konsistenz zwischen SSOTs. Da crosscheck diese Referenzen bereits parst, genügt es, dieselbe Infrastruktur wiederzuverwenden: Eine Graphentraversierung reicht aus, um die Feature Chain zu extrahieren.


Der Traversierungspfad

Mit der operationId als Startpunkt entfaltet sich der Referenzgraph wie folgt:

operationId (Startpunkt)
├── OpenAPI → Pfad + Methode
├── SSaC → Service-Funktionsdatei
│   ├── @get → DDL-Tabellen
│   ├── @auth → Rego-Richtlinienregeln
│   ├── @state → Mermaid stateDiagram-Übergänge
│   ├── @call → Func Spec-Implementierungen
│   └── @publish → Queue-Abonnenten
├── Gherkin → Szenarien, die die operationId referenzieren
└── STML → Frontend-Dateien, die den Endpoint referenzieren

Jeder Zweig folgt nur einer einzigen symbolischen Referenzebene. Die Traversierung ist breit statt tief. Alle Spuren, die ein Feature in den verschiedenen Schichten hinterlässt, werden vollständig sichtbar.


Was sich dadurch ändert

Änderungsumfang bestimmen

„Wo muss ich anfassen, um dieses Feature zu reparieren?"

Um diese Frage zu beantworten, liest man bisher Code, führt Grep aus und fragt Kollegen. Feature Chain ersetzt diese Frage durch einen einzigen Befehl. Keine Datei geht verloren — solange eine symbolische Referenz vorhanden ist.

KI-gestützte Code-Änderungen

Wenn man einer KI eine Feature-Änderung überträgt, ist die größte Hürde, „den Änderungsumfang mitzuteilen". Damit die KI präzise arbeiten kann, müssen alle relevanten Dateien im Kontextfenster vorhanden sein — doch welche Dateien relevant sind, muss der Mensch selbst beurteilen.

Mit Feature Chain ist das anders. Gibt man nur die operationId an, wird der gesamte Änderungsumfang automatisch identifiziert. Der Kontext für die KI ist vollständig und lückenlos vorbereitet.

Code Review

Beim Review eines PRs lässt sich der Verdacht „Wenn dieses Feature geändert wurde, hätte auch jene Datei geändert werden müssen" sofort durch Abgleich mit der Chain überprüfen. Inkonsistenzen zwischen Schichten werden durch die Struktur erkannt — nicht durch den Menschen.

Onboarding

Wenn ein neu hinzugekommener Entwickler fragt: „Wie funktioniert AcceptProposal?" — eine Feature Chain genügt als Antwort. Von der API bis zur DB, von der Autorisierungsrichtlinie bis zum Testszenario — die gesamte Topologie eines Features auf einen Blick.


Warum operationId?

Die Wahl des Startpunkts ist entscheidend. Feature Chain wählt die operationId.

Der Grund ist einfach. In einer Fullstack-Anwendung ist die Einheit eines Features der API-Endpunkt. Wenn der Benutzer einen Button drückt, wird eine API aufgerufen; diese API führt die Service-Logik aus, liest die Datenbank, prüft die Autorisierung und löst Zustandsübergänge aus. Der Startpunkt all dieser Abläufe ist die operationId.

Die operationId ist bereits im OpenAPI-Spec definiert und ein teamweit geteilter Name. Wenn jemand sagt „AcceptProposal muss geändert werden", denken Backend-Entwickler, Frontend-Entwickler und QA dasselbe. Mit diesem einen universellen Namen den gesamten Stack zu durchqueren — das ist das Design von Feature Chain.


Voraussetzungen

Damit Feature Chain funktioniert, gibt es eine Voraussetzung:

  1. Die Quellen müssen einander symbolisch referenzieren. Die Direktiven @get, @auth, @state und @call in SSaC müssen explizit auf andere SSOTs verweisen. Wenn Referenzen implizit sind — etwa wenn ein DB-Tabellenname nur als Zeichenkette im Code vorkommt — kann er nicht nachverfolgt werden.

  2. crosscheck muss bestanden werden. Da Feature Chain symbolischen Referenzen folgt, führen ungültige Referenzen zu falschen Ergebnissen. crosscheck garantiert die Konsistenz der Referenzen; Feature Chain traversiert darauf aufbauend.

Das ist der Grund, warum Feature Chain kein universelles Werkzeug ist. Es kann nicht auf beliebige Projekte angewendet werden. Es funktioniert nur in Projekten, in denen Referenzen zwischen Quellen explizit entworfen wurden — in Strukturen wie fullend, bei denen SSOTs einander explizit referenzieren.


Ausblick: GEUL + SILK

Derzeit traversiert Feature Chain die Parser jedes SSOTs nacheinander. SSaC-Parser, DDL-Parser, Rego-Parser und Mermaid-Parser werden einzeln aufgerufen, und die Ergebnisse werden zusammengeführt.

Wenn alle SSOTs in einen GEUL-Graphen konvertiert werden, wird Feature Chain zu einer einzigen Indexabfrage. Mit SILKs bitweiser AND-Operation auf dem SIDX können alle mit einer operationId verbundenen Knoten in einer einzigen Abfrage extrahiert werden.

Von der parserspezifischen Traversierung zur Graphabfrage. Das Interface von Feature Chain bleibt gleich — das Innere ändert sich grundlegend.


Zusammenfassung

In einer Fullstack-Anwendung steckt ein „Feature" nicht in einer einzigen Datei. Es erstreckt sich über mehrere Schichten, und diese Schichten referenzieren einander. Feature Chain folgt diesen Referenzen und extrahiert automatisch den gesamten Umfang eines Features.

Gibt man eine operationId ein — vom API-Spec bis zum DB-Schema, von der Autorisierungsrichtlinie bis zum Testszenario — werden dutzende Grep-Aufrufe durch einen einzigen Befehl ersetzt.

Code: github.com/park-jun-woo/fullend