| name | dataflow-mapping |
| description | Trace and document how data transforms through a multi-step pipeline or function chain, showing intermediate state at each step with concrete example values. Use when explaining a data pipeline or complicated codepaths, tracing how a value changes across function calls, answering questions like "how does X get to Y", or producing a step-by-step dataflow walkthrough for a code review or design doc. |
Dataflow Mapping
Produce annotated pseudocode traces that show exactly how data changes at each step. Prefer concrete example values over abstract descriptions. The reader should be able to follow one piece of data from input to output without reading the source.
Format
-- <stage name> --
<data state with concrete values>
step โ <what happens> โ <resulting state>
step โ <what happens> โ <resulting state>
โ <output type> { field: value, ... }
Label each stage with the function or method responsible. Use โ to show transformations inline. Use indented continuation lines for multi-step operations within a single stage. Show the output type at the end of each stage.
Use โ and โ for pass/fail outcomes. Use โ for annotations explaining why a value is what it is.
When to use which depth
- Single function: show input โ output only
- Multi-stage pipeline: show intermediate state after each stage
- Authorization/filtering flows: show per-item decisions, then the final set
Examples
Example 1 โ multi-stage pipeline with per-row filtering
-- HTTP response (JSON) --
row 0: { id: 1, owner_id: 42, name: "foo", visibility: "private" }
row 1: { id: 5, owner_id: 99, name: "bar", visibility: "public" }
-- parse_rows() โ Vec<Record> --
records = [
Record { id: 1, owner_id: 42, name: "foo", visibility: Private, authorized: true },
Record { id: 5, owner_id: 99, name: "bar", visibility: Public, authorized: true },
]
-- collect_auth_checks() --
ids = {}
record 0 โ owner_id = 42, policy = "read"
ids[("projects", "read")].insert(42) โ { ("projects","read"): {42} }
record 1 โ owner_id = 99, policy = "read"
ids[("projects", "read")].insert(99) โ { ("projects","read"): {42, 99} }
โ AuthCheck { resource: "projects", policy: "read", ids: [42, 99] }
-- auth service round-trip --
request: { resource: "projects", policy: "read", ids: [42, 99] }
response: { 42: true, 99: false }
-- apply_decisions() --
record 0 โ owner_id = 42 โ decisions.get(42) = true โ record stays
record 1 โ owner_id = 99 โ decisions.get(99) = false โ record.set_unauthorized()
โ records = [
Record { id: 1, ..., authorized: true }, โ returned to caller
Record { id: 5, ..., authorized: false }, โ filtered out
]
Example 2 โ key transformation through a compile pipeline
-- Input --
{ "type": "query", "node": { "id": "n", "entity": "Invoice" } }
-- normalize() --
node.entity = "Invoice"
schema.get("Invoice").auth_column = "account_id" โ not the PK
node.auth_id_column = "account_id" โ set from schema
entity_auth["Invoice"] = AuthConfig {
resource: "accounts",
policy: "read_billing",
id_column: "account_id",
owner_type: Some("Account"),
}
-- codegen() --
SELECT n.account_id AS _auth_n_id โ auth_id_column used here, not "id"
n."type" AS _auth_n_type
ctx.entity_auth = { "Invoice" โ AuthConfig { ... } }
โ CompiledQuery { sql: "SELECT n.account_id AS _auth_n_id ...", ctx }
Example 3 โ single function, input/output only
-- build_auth_map(schema) --
input: schema entities with auth config
"Account" โ { resource: "accounts", policy: "read", id_column: "id" }
"Invoice" โ { resource: "accounts", policy: "read_billing", id_column: "account_id" }
"User" โ { resource: "users", policy: "read_user", id_column: "id" }
output: HashMap<String, AuthConfig> {
"Account" โ AuthConfig { resource: "accounts", policy: "read", auth_col: "id", owner: None }
"Invoice" โ AuthConfig { resource: "accounts", policy: "read_billing", auth_col: "account_id", owner: Some("Account") }
"User" โ AuthConfig { resource: "users", policy: "read_user", auth_col: "id", owner: None }
}
Tips
- Pick example values that reveal edge cases (e.g. one authorized ID and one denied).
- When two stages share the same data, call it out explicitly:
โ same value used in apply_decisions().
- For
HashMap/HashSet collections, show the accumulation across iterations, not just the final state.
- Omit fields that don't change or aren't relevant to the question being answered.
- Adapt type names and field names to the actual codebase โ the format is generic, the values should be concrete.