ci/woodpecker/pr/ci Pipeline was successful
Blocker (rev-security-01 review 259): admin token, generated password and minted seat token travelled curl ARGV (three Authorization sites, -u at the mint, inline -d bodies), leaking to /proc cmdline and bash -x traces — the durable password under must_change_password:false is a live credential. All three now travel in 0600 staging files: --config for the Authorization header (the landed gitea_write_auth_config pattern), a user= directive for basic auth at the mint, --data @file for bodies. Unlinked after each use; M6 asserts no call is unauthenticated and no body is inline. Scope pin (SF2 + rev-security-01 M1, same defect): a mutant writing the REQUESTED scopes passed green because the grep target appears in both sets. M7 now asserts write:issue (requested, not granted) is ABSENT; mutant killed. SF3: hyphenated instance overrides map hyphen->underscore exactly like seat-logins.sh (url_override_var); M8 pins it; the uppercase-only mutant dies at the invalid-variable-name refusal again, now by design. SF1: mint-seat-credential.sh mode 755 (update-index), README invocation updated to name the now-required MOSAIC_SEAT_EMAIL_DOMAIN. Framework-PR firewall answer (rev-security-01): the email domain has NO default — unset is rc=3 with a named variable (M9); the instance host map stays per the seat-logins.sh precedent already on next. Estate domains belong to the estate, not the tree.
25 lines
2.5 KiB
Markdown
25 lines
2.5 KiB
Markdown
# Fleet tools
|
|
|
|
Seat lifecycle tools for a Mosaic fleet. Paths are relative to
|
|
`packages/mosaic/framework/tools/fleet/` (deployed to `~/.config/mosaic/tools/fleet/`).
|
|
|
|
| Script | Purpose |
|
|
| ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `start-agent-session.sh` | launch, stop, or attach a roster-driven agent session (reads `<seat>.env.generated`, honours `MOSAIC_TMUX_SOCKET`) |
|
|
| `seat-logins.sh` | project seat tokens into `tea` logins named `<instance>-<seat>` (dry-run by default, `--apply`, `--adopt`) |
|
|
| `mint-seat-credential.sh` | create the Gitea account for a seat on every configured instance, mint a token, write the seat's credential slot, then project it into `tea` |
|
|
| `start-interaction-service.sh`, `print-interaction-effective-policy.sh`, `start-tmux-holder.sh` | operator interaction service and tmux holder |
|
|
|
|
## Onboarding a seat's credential
|
|
|
|
```
|
|
MOSAIC_ADMIN_SEAT=<admin-seat> MOSAIC_SEAT_EMAIL_DOMAIN=<domain> mint-seat-credential.sh <seat>
|
|
```
|
|
|
|
- The admin token is read from `$MOSAIC_BRAIN_HOME/fleet/agents/<admin-seat>/secrets/gitea-<instance>-<admin-seat>.token`. It is never printed.
|
|
- `MOSAIC_SEAT_EMAIL_DOMAIN` is required (no default): the framework ships no estate-specific domain.
|
|
- Instances default to the map shared with `seat-logins.sh`; `MOSAIC_GITEA_INSTANCES="a b"` limits the set and `MOSAIC_GITEA_URL_<INSTANCE>` overrides a server URL (hyphens in the instance name become underscores in the variable, as in `seat-logins.sh`).
|
|
- The seat slot is written from the mint response: `.token`, `.scopes` (what was granted), `.principal`, each mode 600.
|
|
- `tea` absent is a warning, not a failure: REST-path wrappers work with the token alone.
|
|
- Regression suite: `test-mint-seat-credential.sh` (hermetic, mock curl, no network).
|