Skip to content

Say what the parts are, where they meet, and which meeting is trusted - #260

Merged
fstubner merged 1 commit into
mainfrom
docs/architecture-parts-boundaries-trust
Aug 28, 2026
Merged

fstubner merged 1 commit into
mainfrom
docs/architecture-parts-boundaries-trust

Conversation

@fstubner

Copy link
Copy Markdown
Owner

docs/ARCHITECTURE.md gains the three sections the acceptance contract asks for — Parts, Boundaries, Trust — which it did not have. The existing Ownership Map, Compatibility Rules and Contribution Gates are kept; they answer a different question.

Why the Trust section is the point

The MCP surface takes arguments chosen by a model that may be repeating something it read on a scanned host. Two guards exist for exactly that, and neither was written down anywhere a reader would find:

  • server/targets.rs — refuses anything outside local scope (is_local_scope, ensure_ip_allowed, public_targets_allowed), so a prompt-injected model cannot point the scanner at strangers.
  • server/limits.rs — caps what a scanned host can put into a model's context: MAX_BANNER_CHARS 256, MAX_RESULT_BYTES 1 MiB, over REMOTE_TEXT_KEYS (banner, hex_preview, info).

Also recorded: remote text is data and never markup or control sequences (trace output is asserted free of them in tests/test_trace.rs), and privilege failures surface rather than silently degrading — arp -d * exiting 0 while printing "requires elevation" is why that rule is written down.

Every claim was read out of the source before being written.

The gate still will not check it

Worth stating plainly, because "fixed for the gate" would be misleading. The document is required only when the project classifies as multi_part, and classify.cjs decides that from:

multiPart = (distinctServerPresent && frontendPresent)
         || (root package.json with >1 workspaces)

distinctServerPresent matches server.ts / api.js-style filenames (JS/TS extensions only) or a standalone HTTP framework dependency (for Rust: actix-web, rocket, axum, warp). A JSON-RPC-over-stdio MCP server in crates/netscli-mcp/src/server.rs matches neither, and this repo has no root package.json. So a product with five deployables and a genuine trust boundary classifies single-part, and the architecture check is skipped — check-architecture.js returns SHIP with "single-part project; architecture doc not required".

Since the gate would not validate the headings, I checked them against its own matcher directly:

Parts       heading=true  hasContent=true
Boundaries  heading=true  hasContent=true
Trust       heading=true  hasContent=true

sectionHasContent is the stricter one, added after a document of three empty headings passed and shipped.

Unrelated, same session

cargo clean reclaimed 26.4 GiB (33,533 files). target/ is gone and will rebuild on the next build.

The acceptance contract wants ARCHITECTURE.md to answer three questions --
Parts, Boundaries, Trust -- and this document answered none of them. It
described ownership of directories, which is useful and is kept, but a
reader could not have told from it which pieces are separately deployable,
where one hands work to another, or which of those hand-offs is the one
that matters.

The Trust section is the point. The MCP surface takes arguments chosen by a
model that may be repeating something it read on a scanned host, and two
guards exist for that: targets.rs refuses anything outside local scope, and
limits.rs caps what a scanned host can put into a model's context. Both were
written deliberately and neither was written down anywhere a reader would
find. Remote text being data rather than markup, and privilege failures
surfacing rather than degrading, are recorded for the same reason.

The gate will not evaluate any of this here. It requires the document only
for multi-part projects, and its classifier decides that from JavaScript and
TypeScript server signals plus a root package.json workspaces array. A
JSON-RPC-over-stdio server written in Rust is invisible to it, so a product
with five deployables and a real trust boundary classifies as single-part
and the check is skipped. The headings were verified against the gate's own
matcher instead: all three satisfy hasHeading and sectionHasContent.
@fstubner
fstubner merged commit a47793e into main Aug 28, 2026
13 checks passed
@fstubner
fstubner deleted the docs/architecture-parts-boundaries-trust branch August 28, 2026 12:39
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.

1 participant