Commit Graph
2 Commits
Author SHA1 Message Date
fargo d789a43cae test(git): hermetic fixtures for issue-create harnesses (#1282-#1287)
ci/woodpecker/pr/ci Pipeline was canceled
test-issue-create-body-safety.sh and test-issue-create-interactive-auth.sh
inherited the seat's real HOME and global git config. With the #1280 fix
activating identity mode BEFORE the tea path, a workstation-global
mosaic.gitIdentity resolved inside the fixture repo, and the wrapper's
API fallback posted to the LIVE forge with a real per-slot token — six
real issues (#1282-#1287, authored mos-dt-0, closed with provenance by
fred within the hour).

Neutralize the source the resolver actually reads, and prove it by making
the resolution fail. A control that does not make the thing fail has not
been shown to control it. The earlier attempted neutralization pinned
MOSAIC_CREDENTIALS_FILE to a fake — a real guard aimed at an adjacent
input: the identity arm reads the per-slot token file directly and never
consults credentials.json. Hence env -i with a fake HOME and
GIT_CONFIG_GLOBAL=/dev/null (severing the global identity) rather than
one more targeted variable, plus a curl tripwire stub in the body-safety
harness so ANY provider request is a loud test failure instead of a live
write.
2026-08-17 15:19:04 -05:00
fargo 19ad93999f fix(git): identity-first principal resolution across write wrappers (#1280)
MOSAIC_GIT_IDENTITY=fargo produced objects attributed to mos-dt-0: every
write wrapper resolved its acting principal from tea's login list, which
enumerates whatever logins the host happens to hold and knows nothing
about which seat is calling. The identity-aware code was present and
correct but unreachable on the happy path — it sat on arms that only ran
when tea failed.

One shared resolver, not twenty patches: resolve_gitea_principal() in
detect-platform.sh implements the precedence (explicit --login beats
MOSAIC_GIT_IDENTITY / worktree git config mosaic.gitIdentity; the tea
login list is the LAST resort), fails loud (nonzero, naming the identity
or login and the expected slot path) when the requested principal has no
credential, and never prints a token value. gitea_identity_token_slot()
is the single source of truth for the slot layout, shared with
get_gitea_token, so resolver and token resolution cannot disagree.

Call-site conversions (the proving five): pr-review.sh (principal
resolved once for every action; the comment action now honors --login),
issue-comment.sh, pr-create.sh (identity mode reaches the REST API on the
HAPPY path — tea is never consulted, so the login list cannot shadow the
identity; --login wins even on the tea-failure fallback arm),
issue-create.sh (same), pr-merge.sh (gains --login; --dry-run reports the
principal the merge WOULD act as, resolved exactly as the merge resolves
it; no cross-principal fallback — an identity-bound 401 is a hard stop).

Remaining wrappers are call-site conversions onto the same resolver,
measured: write-path issue-assign, issue-close, issue-edit, issue-reopen,
milestone-close, milestone-create, pr-close; read-path issue-list,
milestone-list, pr-list, pr-view (issue-view mixed). pr-diff, pr-metadata,
pr-ci-wait and ci-queue-wait already inherit identity-first resolution
via get_gitea_token.

Known interaction: on a host with a workstation-GLOBAL mosaic.gitIdentity,
this fix activates identity mode for every seat that has not set a local
one — correct behavior driven by a wrong configuration (measured:
#1282-#1287, six accidental live issues, closed with provenance by fred).
Set mosaic.gitIdentity per-worktree, never --global.

Tests: test-gitea-principal-resolution.sh (resolver matrix — identity
present/absent, --login precedence, env vs git-config, unrecognized-host
containment, slot-path-by-path-never-by-value); test-pr-create-identity-
first.sh (the load-bearing ordering test: identity arm REACHED on the
happy path with tea never invoked, fail-loud BEFORE any write on a
missing slot, --login wins, default preserved); test-pr-merge-principal-
resolution.sh (dry-run truthfulness, merge credential binding, unknown
--login never reaches the provider). All wired into test:framework-shell.

Sabotage control: precedence inverted to tea-list-first inside the
resolver -> exactly the three new suites redden with the #1280
signatures (identity resolves to the tea-list account; missing slot
returns rc=0 with silent fallthrough) while all 11 pre-existing git
suites stay green; restored byte-identical (sha256 verified); all 14
green again.
2026-08-17 15:18:54 -05:00