Feature Chain — Track the Full Stack with a Single operationId

What files do you need to touch to change one feature? Give it an operationId and you have your answer.


The Problem

In a full-stack application, a “feature” doesn’t live in a single file.

Say you need to modify a feature called AcceptProposal. That feature exists in the API spec, in the service logic, in the database schema, in the authorization policy, in the state transition diagram, in external function calls, in test scenarios, and in the frontend.

There have been two ways to figure out that full scope:

  1. Run grep dozens of times
  2. Trace through the code manually

Both are slow. Both miss things. Tracking cross-layer references — API spec to service, service to DB schema, service to authorization policy — without gaps is genuinely difficult for a human to do reliably.

But if each layer’s source already references other layers symbolically, following those references is all it takes to surface the full scope automatically.


What Feature Chain Is

Feature Chain extracts every source node connected to a single API feature (operationId).

Starting from one operationId, it follows inter-source symbol references and outputs every related file and line number in a single pass. Dozens of greps become one command.

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

The entire structure of a single feature fits on one screen. Layers with no connection are omitted.


Why It Works

This isn’t magic. It works because the sources already reference each other.

In the fullend framework, each SSOT (Single Source of Truth) layer points symbolically to other layers:

  • SSaC @get Model.Method → DDL table
  • SSaC @auth action resource → Rego authorization policy
  • SSaC @state diagramID → Mermaid state diagram
  • SSaC @call pkg.Func → FuncSpec implementation
  • OpenAPI operationId → SSaC filename
  • Gherkin action step → operationId
  • STML endpoint → OpenAPI path

These references were originally designed for crosscheck — a tool that validates consistency across SSOTs. Since crosscheck already parses them, reusing that infrastructure means feature chain extraction is just a graph traversal.


The Traversal Path

Starting from an operationId, the reference graph unfolds like this:

operationId (entry point)
├── OpenAPI → path + method
├── SSaC → service function file
│   ├── @get → DDL tables
│   ├── @auth → Rego policy rules
│   ├── @state → Mermaid stateDiagram transitions
│   ├── @call → FuncSpec implementations
│   └── @publish → queue subscribers
├── Gherkin → scenarios referencing the operationId
└── STML → frontend files referencing the endpoint

Each branch follows only one hop of symbol reference. It’s broad, not deep. Everything a feature touches across layers becomes visible.


What This Changes

Scoping Changes

“What do I need to touch to fix this feature?”

To answer that question, we read code, run grep, and ask colleagues. Feature Chain replaces that question with a single command. No file slips through — as long as there’s a symbol reference.

AI-Assisted Code Changes

The hardest part of delegating a code change to AI is telling it the scope. The AI can only make accurate changes if you load all relevant files into the context window — and a human has to decide which files are relevant.

With Feature Chain, that changes. One operationId is all you need to identify the full scope of the change. The context you hand off to the AI is complete, with nothing missing.

Code Review

When reviewing a PR, the suspicion “if this feature changed, shouldn’t that file have changed too?” can be verified instantly by comparing against the chain. The structure catches cross-layer inconsistencies so humans don’t have to.

Onboarding

When a new developer asks “how does AcceptProposal work?”, showing them a Feature Chain is enough. From API to DB, from authorization policy to test scenarios — the full terrain of the feature is visible at a glance.


Why operationId

The choice of starting point matters. Feature Chain uses operationId.

The reason is straightforward. In a full-stack application, the unit of a feature is the API endpoint. A user clicks a button, an API is called, that API runs service logic, reads the DB, checks authorization, and transitions state. The operationId is where all of that begins.

operationId is already defined in the OpenAPI spec and is a name shared across the whole team. When someone says “we need to change AcceptProposal,” backend engineers, frontend engineers, and QA all picture the same thing. Threading the entire stack through that one universal name is the core design of Feature Chain.


Prerequisites

Feature Chain has prerequisites:

  1. Sources must reference each other symbolically. SSaC directives — @get, @auth, @state, @call — must explicitly point to other SSOTs. If references are implicit — for example, a DB table name that only appears as a string inside code — they can’t be traced.

  2. crosscheck must pass. Feature Chain follows symbol references, so invalid references produce incorrect results. crosscheck guarantees reference consistency; Feature Chain traverses on top of that.

This is why Feature Chain isn’t a general-purpose tool. It can’t be applied to any arbitrary project. It only works in projects where inter-source references are by design — structures like fullend, where SSOTs explicitly point to each other.


The Future: GEUL + SILK

Currently, Feature Chain traverses each SSOT parser in sequence — calling the SSaC parser, DDL parser, Rego parser, and Mermaid parser separately, then combining the results.

Once all SSOTs are converted to a GEUL graph, Feature Chain becomes a single index query. Using SILK’s SIDX bitwise AND operation, every node connected to an operationId can be extracted in one shot.

From per-parser traversal to graph query. Feature Chain’s interface stays the same; its internals change fundamentally.


Summary

In a full-stack application, a “feature” doesn’t live in a single file. It spans multiple layers, and those layers reference each other. Feature Chain follows those references to automatically extract the full scope of any feature.

Give it one operationId — from API spec to DB schema, from authorization policy to test scenarios — and dozens of greps become a single command.

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