Skip to content

map: runtime parameter coordinates, spans and fingerprints (schema v2) - #124

Merged
patchstackdave merged 2 commits into
mainfrom
feat/map-runtime-coordinates
Aug 13, 2026
Merged

map: runtime parameter coordinates, spans and fingerprints (schema v2)#124
patchstackdave merged 2 commits into
mainfrom
feat/map-runtime-coordinates

Conversation

@patchstackdave

Copy link
Copy Markdown
Contributor

Track 1 of the agreed two-track plan — finish trusted coordinates before building candidate generation, without blurring them.

Stacked on #123. This branch includes #123's commit (full-path matching + exact sink-call ownership); merge that first and this diff shrinks to its own commits.

The point

Give a server everything it needs to compile a map input into a rule-engine parameter — and refuse to emit a coordinate it cannot compile.

Every input now carries source and runtimeParameter:

{ "name": "shipping.email", "source": "server-fn-data", "runtimeParameter": "post.shipping.email" }
source coordinate
json-body / form-body / multipart / body / server-fn-data post.<dotted path>
query get.<name>
cookie cookie.<name>
file files.<field>
header server.HTTP_<UPPER_SNAKE>

Server-function args map to post.* because createServerFnGuard delivers them as the JSON body.

Two cases deliberately return null + a reason

Both verified against engine/request.js, not assumed — a coordinate the resolver can't resolve compiles into a rule that silently never matches, which is worse than emitting none:

  • Route params have no coordinate. The resolver exposes get/post/request/cookie/server.*/filesnot req.params. Emitting get.tenant would be a dead rule.
  • Array paths have no dotted coordinate. #getNestedValue walks own properties, so tags[].label needs an array_key_value rule instead.

ruleGeneratable, separate from confidence

{ "confidence": "precise", "ruleGeneratable": false,
  "ruleGeneratableReasons": ["sink argument role is not modelled yet"] }

precise means the source reaches the sinknot authorization to block traffic. Every remaining obstacle is listed, so this doubles as the improvement queue. Nothing is generatable yet: sink argument roles are unmodelled, which is exactly the Track-2 gate.

Coordinates you can invalidate

Endpoints and sinks carry start/end (documented as UTF-16 offsets), and endpoints a content fingerprint, so a server can reject stale coordinates after a deploy. Schema version bumped to 2.

A recall bug the example outputs caught

Generating sample maps exposed that the highest-value flows never reached precise: req.body.webhookUrl produced read path body.webhookUrl while the input is namespace-relative (webhookUrl). Fixed — SSRF / traversal / command-injection now come out precise with correct coordinates, and are covered by tests. The residual risk direction is a false negative, not a false positive.

Also: PS_MAP_DEBUG surfaces extractor errors — the per-file fail-open is right for production but made a crash indistinguishable from an unparseable file, and it hid a self-recursion bug during this change.

798 tests green; typecheck clean.

@coderbuds

coderbuds Bot commented Aug 13, 2026

Copy link
Copy Markdown

Adds runtime parameter coordinates and spans to input map schema v2.

🎯 Quality: 91% Elite · 📦 Size: Extra Large — strongly consider breaking this down

🛡️ Standards: no pre-flight fit check ran for this change — wire assess-change-fit into your coding agents to catch size before opening.

📈 This month: Your 57th PR — above team average · Averaging Excellent

See how your team is trending →

@patchstackdave

Copy link
Copy Markdown
Contributor Author

/review

patchstackdave and others added 2 commits August 13, 2026 15:12
Track 1 of the agreed two-track plan ("trusted coordinates" before "candidate
generation"): give a server everything it needs to compile a map input into a rule
engine parameter — and, crucially, refuse to emit a coordinate it cannot compile.

- Every input now carries `source` (json-body / form-body / query / route-param /
  header / cookie / file / server-fn-data / …) and `runtimeParameter`, the EXACT
  engine parameter that addresses it: `post.shipping.email`, `get.q`,
  `server.HTTP_X_API_KEY`, `cookie.session`, `files.avatar`. Server-function args are
  `post.<path>` because createServerFnGuard delivers them as the JSON body.
- Two cases deliberately return `runtimeParameter: null` + a reason, both verified
  against engine/request.js rather than assumed:
    * ROUTE PARAMS have no coordinate — the resolver exposes get/post/request/cookie/
      server/files, but not `req.params`. Emitting `get.tenant` would compile a rule
      that silently never matches.
    * ARRAY PATHS have no dotted coordinate — `#getNestedValue` walks own properties, so
      `tags[].label` needs an `array_key_value` rule instead.
- `ruleGeneratable` + `ruleGeneratableReasons` on every flow, deliberately SEPARATE from
  `confidence`: "the source reaches the sink" is not authorization to block traffic.
  Everything still missing is listed, so it doubles as the improvement queue. Nothing is
  generatable yet — sink argument roles are unmodelled, which is the Track-2 gate.
- Endpoints and sinks carry `start`/`end` (documented as UTF-16 offsets) and endpoints a
  content `fingerprint`, so a server can reject stale coordinates after a deploy.
- Schema version bumped to 2.

Also: PS_MAP_DEBUG surfaces extractor errors. The per-file fail-open is right for
production but made a crash indistinguishable from an unparseable file — it hid a
self-recursion bug in the new span helper during this change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ty families)

Generating example outputs surfaced a recall bug in exactly the flows a candidate
compiler would target first. `req.body.webhookUrl` produced the read path
`body.webhookUrl`, but inputs are named relative to their namespace (`webhookUrl`, whose
coordinate is `post.webhookUrl`) — so the two never matched and SSRF / traversal /
command-injection flows all came out `heuristic`:

  axios.get(req.body.webhookUrl)     webhookUrl -> http  now precise (post.webhookUrl)
  fs.readFileSync(req.body.filename) filename   -> fs    now precise (post.filename)
  exec(req.body.command)             command    -> exec  now precise (post.command)
  fs.readFileSync(req.query.file)    file       -> fs    now precise (get.file)

A leading request-namespace segment is dropped when the root is the request object. Note
the direction of the remaining risk: a body field genuinely named `body`/`query` inside a
differently-rooted container would be stripped too, which loses precision (heuristic)
rather than inventing it — the safe direction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@patchstackdave
patchstackdave force-pushed the feat/map-runtime-coordinates branch from 1e97ba8 to 8741138 Compare August 13, 2026 13:13
@patchstackdave
patchstackdave merged commit 9f5cb12 into main Aug 13, 2026
5 checks passed
@patchstackdave
patchstackdave deleted the feat/map-runtime-coordinates branch August 13, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants