Skip to content

I1031 — A served surface says which checkout it is serving

Make every surface a process serves name the repository it is serving — its root and its identity — so that a reader can tell at a glance whether the answers in front of them come from the tree they are working in.

DONE wave 0 · p1 · implementation profile · parallel safe

Part of capability-graph — One capability graph, two projections, and no second inventory of what this repository can do.

Objective

Make every surface a process serves name the repository it is serving — its root and its identity — so that a reader can tell at a glance whether the answers in front of them come from the tree they are working in.

Why

This cost a real hour. A browser held a Swagger page from a server that had exited, its requests failed with a message blaming CORS, and the live server on another port turned out to be serving a scratchpad worktree of a different session entirely — so even the document being read was that other tree's, including a sentence about the routes that this tree had already corrected. Nothing on the page said which checkout answered it. Several sessions share one machine and each may bind its own server; a surface that does not name its tree invites exactly this conclusion, that the tool is broken, when the tool is fine and the address is wrong.

Current state

Half of this landed on 2026-09-10 outside the plan. ADR 0035 added repository::git_identity, and the home page and the index route answer it beside the checkout's own repository_id and linked_worktree, so a reader can tell which repository and which checkout answered; the identity comes from the repository model and names no host path (PR #153, PR #164). Two criteria are still open: the interactive API shell (apps/majordomus-cli/src/http/swagger.rs) names neither root nor identity, and no test serves two roots and proves each surface names its own. Measured on master 6042f4286, 2026-09-10.

Desired state

Every served surface carries the repository root and identity it is answering for, close enough to the content that a reader sees it without asking for it.

Scope

  • apps/majordomus-cli/src/http/router.rs
  • apps/majordomus-cli/src/http/swagger.rs
  • apps/majordomus-cli/src/web/home.rs
  • test/cases/3110_a_served_surface_names_its_checkout.sh

Out of scope

  • Publishing an absolute developer path to anything but a loopback surface
  • A second identity beside the one the repository model already holds
  • Changing what any surface serves; this changes only what it says about itself

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • The home page names the repository root and identity the process is serving, not only the surfaces it exposes
  • The interactive API shell names the same root, so a page fetched from one server cannot be mistaken for another's
  • The identity comes from the repository model rather than from a second inspection
  • No surface names the repository's location on the host: the identity says which checkout answered, never where it sits, and a test proves no served or published output carries an absolute path
  • The behaviour is exercised by a test that serves two roots and proves each surface names its own

Validation

  • cargo test --workspace --all-features
  • bash test/run.sh

Evidence required

  • identity_on_surfaces
  • published_carries_no_path

Evidence

coverstypecommandresultat commit
identity_on_surfacestestbash test/run.sh 3110_a_served_surface_names_its_checkoutok 3110: two roots (primary + linked worktree) served at once; / JSON, / HTML and /swagger each name their own repository_id, the shared git_repository_id, branch and head, never the other's; FAIL on master binary d116266d116266
published_carries_no_pathtestbash test/run.sh 3110_a_served_surface_names_its_checkoutok 3110 section 3: /, /swagger, /openapi.json, /api/v1/ of both roots carry no fixture root, $ROOT, $HOME or leak-patterns.tsv machine path; scripts/ci/no-machine-paths $ROOT exits 0d116266
identity_on_surfacestestbash test/run.sh 3110_a_served_surface_names_its_checkoutok, 1 passed on master 707a04c7ce8 (2026-10-17); full suite: ci check-run success on 4a4573690f8, run 39049547899 job 117473773693; master 707a04c7ce8 adds only the v0.29.0 release record707a04c
published_carries_no_pathtestbash test/run.sh 3110_a_served_surface_names_its_checkoutok, 1 passed on master 707a04c7ce8 (2026-10-17)707a04c

Risk

The obvious fix — printing the root — is the one to refuse: it would leak the host's directory layout to whoever can reach the socket, and the incident is solved by saying which checkout answered, not where it lives.

Timeline

started
2026-10-16T11:59:02Z
verified
2026-10-16T13:51:16Z
completed
2026-10-17T21:35:04Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I1031.yaml. Read it back with majordomus plan show I1031.

Searches the titles and descriptions of every page this site publishes.