Skip to content

The route-ledger conformance guards' host-app-reach limb scans RAW source, so a prose mention of getRawApp reads as a second reacher #12398

Description

@os-warren

Filed unassigned from #12140's implementation round — an observation, not a claim on anyone's
time, and deliberately not fixed there (that card hardens a dev door and changed no guard).

What was measured

packages/metadata/src/metadata-route-ledger.conformance.test.ts has a limb that asserts an
IDENTITY — "plugin.ts is the only file that reaches for the host app":

const HOST_APP_REACH = /getRawApp|['"`]http-server['"`]|['"`]http\.server['"`]/;
const readSource = (file: string): string => readFileSync(join(SRC_DIR, file), 'utf8');
…
const reaching = packageSourceFiles().filter((f) => HOST_APP_REACH.test(readSource(f)));
expect(reaching, '…').toEqual([HOST_APP_REACH_FILE]);

readSource is the RAW file. Every other limb in that same file runs its input through
stripComments() first, and the file's own header says why:

Strip comments before scanning. Prose cannot mount a route, and this package's headers
quote the wire paths they serve — a raw-text scan would report a documented path as an
unledgered mount.

That ruling is correct and this limb does not apply it. The consequence: a comment in any
non-excluded, non-test source file of the package that quotes getRawApp, 'http-server' or
'http.server' fails the identity assertion, naming a file that reaches for nothing.

Not hypothetical — it fired on #12140's first draft. A docblock added to
packages/metadata/src/routes/hmr-routes.ts explaining why the mount sits outside the auth
seam ("the mount takes the framework-native handle through IHttpServer.getRawApp()") was
enough:

- Expected  - 0
+ Received  + 1
  [
    "plugin.ts",
+   "routes/hmr-routes.ts",
  ]

#12140 worked around it by not repeating the spelling in that module's prose (with a comment
saying why), which is a documentation tax on the module that most needs to explain the seam.

Why it is worth a card rather than a shrug

The failure invites the WRONG repair. The message reads "files reaching for the host HTTP
app … ledger its routes and add its module to MOUNT_SOURCES before adding it here", so the
obvious response to a prose-only hit is to add the file to the expected identity list — which
permanently widens an assertion whose whole value is that it is an identity. A guard that is
green because someone widened its expectation is worse than no guard.

Scope: this is a family, not one file

The same raw-text limb is replicated across at least three packages, each with its own copy of
the regex:

  • packages/metadata/src/metadata-route-ledger.conformance.test.ts (readSource, no strip)
  • packages/cloud-connection/src/cloud-connection-route-ledger.conformance.test.ts (same
    HOST_APP_REACH spelling, readSource, no strip)
  • packages/triggers/trigger-api/src/trigger-api-route-ledger.conformance.test.ts (same limb,
    reads the file inline with readFileSync, no strip)

packages/cli/src/utils/console-route-ledger.conformance.test.ts is in the same family and
should be checked with them.

What a fix would have to keep

Not simply "strip comments everywhere". Two properties are load-bearing and pull in opposite
directions, which is why this wants a considered fix rather than a one-line edit:

  1. Comments must not count — prose cannot reach for anything. This is the fix.
  2. String literals must still count — the limb detects ctx.getService('http.server'),
    so the sibling maskStrings() helper (used by other limbs) must NOT be applied here or
    the limb detects nothing and passes vacuously. Stripping comments is safe; masking strings
    would be a silent disarm.

A fix should also confirm the limb still FAILS on a real second reacher after the change —
the anti-vacuity measurement these guards already carry for their other limbs.

Refs: #12140 (where it was measured) · #11882 (the metadata ledger these limbs guard)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions