Adds an opt-in per-agent Gitea identity so a fleet agent can push/commit/open
PRs under its own token instead of the single shared account, giving
cryptographic author-!=-reviewer separation (Gate-16).
Resolution priority (both tools): MOSAIC_GIT_IDENTITY env > git config
mosaic.gitIdentity (per-worktree, persists on disk) > git-supplied username
(git-credential-mosaic only). If the resolved identity has a token file at
~/.config/mosaic/secrets/gitea-tokens/gitea-{usc,mosaicstack}-<id>.token, that
identity is used; otherwise both tools fall through to the existing
shared-account path unchanged, so this is a no-op on any host without
per-slot tokens configured.
- tools/git/git-credential-mosaic: new git credential helper (get verb).
- tools/git/detect-platform.sh: get_gitea_token() gains the same identity
resolution, prepended ahead of the existing shared-token logic, so API
tooling (pr-create.sh, issue-create.sh, ...) authors under the same
identity as git push/fetch.
- install.sh: explicit chmod +x for git-credential-mosaic (it ships without
a .sh suffix, so the existing *.sh glob does not cover it); tools/** is
already framework-owned so the file syncs automatically.
- tools/git/README.md: documents the feature, the one-time
`git config credential.helper` registration step (deliberately not
auto-wired — see README for why), and the PowerShell-parity decision
(detect-platform.ps1 authenticates via tea logins, not a raw-token
function, so there is nothing to port there).
- tools/git/test-git-credential-mosaic.sh,
tools/git/test-gitea-token-identity.sh: new regression harnesses (red
verified against the pre-patch code) covering identity-resolution
priority, per-host token path selection, and shared-account fallback.
Wired into package.json's test:framework-shell.
Upstreams Mos host-local tooling-patch kit (2026-07-23), Patches 1+2.
Closes #873
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
71 lines
4.0 KiB
Markdown
71 lines
4.0 KiB
Markdown
# Git provider wrappers
|
|
|
|
These scripts provide host-aware GitHub and Gitea issue, pull-request, milestone, and CI operations.
|
|
|
|
## Durable review provenance
|
|
|
|
A successful provider write command—or a wrapper message based only on that command's exit code—is **not** durable review provenance. Review comments count as durable provenance only after the wrapper reads the created provider record back and verifies that it belongs to the intended repository and pull request and contains the exact submitted body (or verifies the provider-returned record ID).
|
|
|
|
`pr-review.sh` therefore fails closed when a Gitea comment cannot be written, its created comment ID cannot be identified, or provider read-back does not match. It reports comment success only after that read-back verification passes.
|
|
|
|
## Per-agent Gitea identity (Gate-16 author≠reviewer)
|
|
|
|
By default, git push/fetch (via `git-credential-mosaic`) and the API wrappers above (via
|
|
`detect-platform.sh`'s `get_gitea_token`) all authenticate as the single shared Gitea
|
|
account/token configured through `tools/_lib/credentials.sh`. That means every agent in a
|
|
fleet commits, pushes, and opens PRs under one identity — with no cryptographic
|
|
separation between an author and a reviewer.
|
|
|
|
Both `git-credential-mosaic` and `get_gitea_token()` resolve an optional **per-agent
|
|
identity** before falling back to the shared account:
|
|
|
|
1. `MOSAIC_GIT_IDENTITY` environment variable, or
|
|
2. `git config --get mosaic.gitIdentity` (set per-worktree; persists on disk across
|
|
non-persistent shells — `git config mosaic.gitIdentity <agent-id>`), or
|
|
3. (git-credential-mosaic only) the username git itself supplies for the credential
|
|
request.
|
|
|
|
If the resolved identity has a token file at
|
|
`~/.config/mosaic/secrets/gitea-tokens/gitea-{usc,mosaicstack}-<agent-id>.token`, that
|
|
identity + token is used. **Nothing configured → nothing changes**: with no per-slot
|
|
token file present, both tools fall through to the existing shared-account path
|
|
unchanged, so this feature is a no-op on any host that hasn't provisioned per-slot
|
|
tokens.
|
|
|
|
### Enabling it for a clone
|
|
|
|
The framework installer syncs `git-credential-mosaic` to
|
|
`~/.config/mosaic/tools/git/git-credential-mosaic` (executable) on every install/update,
|
|
but does **not** register it as git's credential helper automatically. Registration is a
|
|
one-time, explicit step:
|
|
|
|
```bash
|
|
# Per-repo (recommended — scopes the helper to this clone only):
|
|
git config credential.helper "$HOME/.config/mosaic/tools/git/git-credential-mosaic"
|
|
|
|
# Per-worktree identity pin (Gate-16 separation):
|
|
git config mosaic.gitIdentity <agent-id>
|
|
```
|
|
|
|
This is deliberately **not** auto-registered on install/update: `credential.helper` is
|
|
global, order-sensitive git config (`~/.gitconfig`) that can already hold an
|
|
operator-chosen credential manager (keychain, `store`, `manager-core`, …) for
|
|
repositories unrelated to Mosaic. Silently inserting an entry on every framework
|
|
install/upgrade risks reordering or shadowing that operator-owned surface across the
|
|
whole host — the same operator-owned config the installer's manifest system is
|
|
otherwise careful never to touch. Because identity is already resolved per-worktree
|
|
(`mosaic.gitIdentity`), the correct granularity for registering the helper is per-clone
|
|
too, so a documented manual step is the right shape here, not a global auto-write.
|
|
|
|
### PowerShell parity
|
|
|
|
`detect-platform.ps1`'s Gitea wrappers authenticate through `tea` CLI logins
|
|
(`Get-GiteaLoginForHost`), not a raw-token `get_gitea_token`-equivalent function — there
|
|
is nothing to prepend the identity-resolution block to on the PowerShell side. A native
|
|
PowerShell git-credential helper is also unnecessary: `git-credential-mosaic` is invoked
|
|
by git's credential-helper protocol (stdin/stdout), which works identically under Git for
|
|
Windows' bundled `bash`/`sh` when configured via `credential.helper`, without a `.ps1`
|
|
counterpart. A `tea`-login-based per-agent identity for the PowerShell wrappers is a
|
|
separate, larger design (mapping identities to `tea login` profiles) and is out of scope
|
|
here.
|