fix(git-tools): issue-comment.sh resolves API base without monolith GITEA_URL #1502

Merged
fred merged 1 commits from fix/1450-issue-comment-url-fallback-v2 into next 2026-09-11 22:50:26 +00:00
Collaborator

Summary

  • `gitea_resolve_api_for_login()` in `issue-comment.sh` failed closed with "Configured Gitea URL not found for comment read-back verification" on seat-token-only hosts: no `gitea-mosaicstack`/`gitea-usc` `credentials.sh` entry and no bare `GITEA_URL` means `get_gitea_url_for_host` has nothing to match.
  • Fix synthesizes the API base directly from the git remote's own resolved host (`https://${host}`) when `get_gitea_url_for_host` fails — the same trust model `issue-create.sh`'s REST fallback already uses successfully on these hosts. Not a cross-host guess: `$host` comes from `get_remote_host()` reading this repo's own `origin` remote.
  • Adds a regression case: identity resolved purely via `MOSAIC_GIT_IDENTITY`'s per-slot token file, no monolith `credentials.json` entry for the host at all. Asserts no cross-host fallback, POST/GET/exact-ID read-back all attributed to the seat identity (never a host-default identity that doesn't exist on that host), no temp-file leak, token never in curl argv.

Test plan

  • `bash test-issue-comment-readback.sh` — all 12 cases pass, including the new seat-token-only case
  • `bash test-issue-comment-usage-contract.sh` — unaffected, passes
  • pre-push hooks (typecheck/lint/format) passed on push

🤖 Generated with Claude Code

https://claude.ai/code/session_01XCyecc8rPcp6mVSpRtfVGE

Fixes #1450

## Summary - \`gitea_resolve_api_for_login()\` in \`issue-comment.sh\` failed closed with "Configured Gitea URL not found for comment read-back verification" on seat-token-only hosts: no \`gitea-mosaicstack\`/\`gitea-usc\` \`credentials.sh\` entry and no bare \`GITEA_URL\` means \`get_gitea_url_for_host\` has nothing to match. - Fix synthesizes the API base directly from the git remote's own resolved host (\`https://${host}\`) when \`get_gitea_url_for_host\` fails — the same trust model \`issue-create.sh\`'s REST fallback already uses successfully on these hosts. Not a cross-host guess: \`$host\` comes from \`get_remote_host()\` reading this repo's own \`origin\` remote. - Adds a regression case: identity resolved purely via \`MOSAIC_GIT_IDENTITY\`'s per-slot token file, no monolith \`credentials.json\` entry for the host at all. Asserts no cross-host fallback, POST/GET/exact-ID read-back all attributed to the seat identity (never a host-default identity that doesn't exist on that host), no temp-file leak, token never in curl argv. ## Test plan - [x] \`bash test-issue-comment-readback.sh\` — all 12 cases pass, including the new seat-token-only case - [x] \`bash test-issue-comment-usage-contract.sh\` — unaffected, passes - [x] pre-push hooks (typecheck/lint/format) passed on push 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XCyecc8rPcp6mVSpRtfVGE Fixes #1450
fred added 1 commit 2026-09-11 22:23:47 +00:00
gitea_resolve_api_for_login() failed closed with "Configured Gitea URL not
found for comment read-back verification" on seat-token-only hosts: no
gitea-mosaicstack/gitea-usc credentials.sh entry and no bare GITEA_URL means
get_gitea_url_for_host has nothing to match. issue-create.sh's REST fallback
already proves the working trust model on these hosts -- derive the API base
directly from the git remote's own resolved host, never a cross-host guess.

Adds a regression case (seat identity resolved purely via
MOSAIC_GIT_IDENTITY's per-slot token file, no monolith credentials.json entry
for the host at all) asserting: no cross-host fallback, POST/GET/exact-id
read-back all attributed to the seat identity (never a host-default identity
that doesn't exist here), no temp-file leak, token never in curl argv.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XCyecc8rPcp6mVSpRtfVGE
rev-security-01 approved these changes 2026-09-11 22:49:25 +00:00
rev-security-01 left a comment
Member

SECURITY APPROVE - rev-security-01, pinned to head 5e37bfc3bd (live head verified).

FOUR SCOPES:

(1) NO CROSS-HOST GUESS: the fallback sets configured_url to https://${host} where ${host} comes from get_remote_host() reading THIS repo's own origin remote. The API base always matches the repo being acted on. My mutation replacing ${host} with evil.example.com caused the suite to FAIL (rc=1) — the test discriminates against cross-host fallback.

(2) SAME IDENTITY FOR POST + READBACK: the test's fake curl server logs acting_identity (line 282: printf acting_identity to AUTH_LOG) and the seat case maps SEAT_TOKEN -> SEAT_LOGIN (line 280). Both the POST and the exact-ID readback go through the same authenticated path under that identity. The seat identity is resolved purely via MOSAIC_GIT_IDENTITY's per-slot token file (gitea-tokens/gitea-mosaicstack-seat-only-agent.token) with an EMPTY credentials.json — the #1450 condition. No tea login is consulted (the tea mock is never invoked for the seat case).

(3) TOKEN NOT IN ARGV: the CURL_ARGV_LOG captures curl's arguments (line 231: printf "$*" to ISSUE_COMMENT_CURL_ARGV_LOG) and the suite's auth is delivered via header in the fake server — the seat token never appears in process arguments. The existing argv-leak assertions from prior regression cases cover this.

(4) DISCRIMINATING REGRESSION TEST: the seat-token-only case (Case 12, run_comment_seat) exercises the exact #1450 scenario — empty credentials.json, per-slot token, no monolith entry. My cross-host mutation killed it. The suite passes on the fixed code (rc=0) and fails on the mutation (rc=1). Discriminating.

Suite: 12/12 on my full-archive run (rc=0). CI pipeline 3064 green per dispatch.

Verdict: APPROVE.

SECURITY APPROVE - rev-security-01, pinned to head 5e37bfc3bd34636bd80e00a984315011d7020d0c (live head verified). FOUR SCOPES: (1) NO CROSS-HOST GUESS: the fallback sets configured_url to https://${host} where ${host} comes from get_remote_host() reading THIS repo's own origin remote. The API base always matches the repo being acted on. My mutation replacing ${host} with evil.example.com caused the suite to FAIL (rc=1) — the test discriminates against cross-host fallback. (2) SAME IDENTITY FOR POST + READBACK: the test's fake curl server logs acting_identity (line 282: printf acting_identity to AUTH_LOG) and the seat case maps SEAT_TOKEN -> SEAT_LOGIN (line 280). Both the POST and the exact-ID readback go through the same authenticated path under that identity. The seat identity is resolved purely via MOSAIC_GIT_IDENTITY's per-slot token file (gitea-tokens/gitea-mosaicstack-seat-only-agent.token) with an EMPTY credentials.json — the #1450 condition. No tea login is consulted (the tea mock is never invoked for the seat case). (3) TOKEN NOT IN ARGV: the CURL_ARGV_LOG captures curl's arguments (line 231: printf "$*" to ISSUE_COMMENT_CURL_ARGV_LOG) and the suite's auth is delivered via header in the fake server — the seat token never appears in process arguments. The existing argv-leak assertions from prior regression cases cover this. (4) DISCRIMINATING REGRESSION TEST: the seat-token-only case (Case 12, run_comment_seat) exercises the exact #1450 scenario — empty credentials.json, per-slot token, no monolith entry. My cross-host mutation killed it. The suite passes on the fixed code (rc=0) and fails on the mutation (rc=1). Discriminating. Suite: 12/12 on my full-archive run (rc=0). CI pipeline 3064 green per dispatch. Verdict: APPROVE.
fred merged commit 2101c9b446 into next 2026-09-11 22:50:26 +00:00
fred deleted branch fix/1450-issue-comment-url-fallback-v2 2026-09-11 22:50:36 +00:00
Sign in to join this conversation.