fix(auth): mosaic-managed auth lives under the data root, never ~/.pi (#48)
Owner direction: the stack must never impact default harness usage. Correction to M19 as shipped (nothing had been created in ~/.pi — the move breaks nothing). - Mosaic-managed accounts: <dataRoot>/auth/<account>.json, perms 0600 enforced (loose perms flagged in listings, refused by --auth — mirrors gitea-api.sh credential hygiene). - ~/.pi is read-only to the stack, permanently; the only interaction remains the existing read-only container mount of the default credential. Recorded as a ROADMAP standing decision. - auth.sh is now config-driven (data root from config.json, fail closed, consistent with every other tool); status reports both sources labeled. - agent.sh --auth resolution moved after load_config (needs the data root); missing/symlinked/non-0600 accounts refuse. - test-auth.sh: 15 no-Docker cases (accounts-create-nothing, loose-perms refusal, invalid-config refusal added). Test-authoring correction recorded in BUILD-LOG (fixture-state mismatch caught before running). Suites 24/15/90/14/17 + verify green.
This commit is contained in:
+17
-14
@@ -41,25 +41,28 @@ done
|
||||
[ -n "$NAME" ] || { echo "agent: usage: scripts/agent.sh <name> [--mission f] [--workspace ws] [--session s] [--tools list] [--auth account]" >&2; exit 4; }
|
||||
case "$NAME" in *[!A-Za-z0-9._-]*|'') echo "agent: invalid agent name" >&2; exit 4;; esac
|
||||
|
||||
# Named auth account (M19): per-launch credential injection. Resolves
|
||||
# auth.<account>.json beside the active credential file and exports
|
||||
# PI_AUTH_FILE (the compose read-only mount source). A missing or invalid
|
||||
# account refuses - silently falling back to the default credential would
|
||||
# put one account's work on another's identity.
|
||||
if [ -n "$AUTH_ACCOUNT" ]; then
|
||||
case "$AUTH_ACCOUNT" in *[!A-Za-z0-9._-]*|'') echo "agent: invalid auth account name" >&2; exit 4;; esac
|
||||
AUTH_DIR="$(dirname "${PI_AUTH_FILE:-$HOME/.pi/agent/auth.json}")"
|
||||
AUTH_RESOLVED="$AUTH_DIR/auth.$AUTH_ACCOUNT.json"
|
||||
[ -r "$AUTH_RESOLVED" ] && [ ! -L "$AUTH_RESOLVED" ] || { echo "agent: no credential file for auth account '$AUTH_ACCOUNT': $AUTH_RESOLVED" >&2; exit 4; }
|
||||
export PI_AUTH_FILE="$AUTH_RESOLVED"
|
||||
echo "agent: auth: account '$AUTH_ACCOUNT' -> $AUTH_RESOLVED" >&2
|
||||
fi
|
||||
|
||||
load_config
|
||||
load_release
|
||||
bootstrap_runtime_dir
|
||||
ensure_release_aligned
|
||||
|
||||
# Named auth account (M19, corrected per owner in #48): per-launch
|
||||
# credential injection from MOSAIC-MANAGED storage under the data root —
|
||||
# never from inside ~/.pi, which is read-only to the stack. Resolves
|
||||
# <dataRoot>/auth/<account>.json and exports PI_AUTH_FILE (the compose
|
||||
# read-only mount source). Missing, symlinked, or non-0600 files refuse:
|
||||
# silently falling back to another credential would put one account's work
|
||||
# on another's identity.
|
||||
if [ -n "$AUTH_ACCOUNT" ]; then
|
||||
case "$AUTH_ACCOUNT" in *[!A-Za-z0-9._-]*|'') echo "agent: invalid auth account name" >&2; exit 4;; esac
|
||||
AUTH_RESOLVED="$MOSAIC_DEV_DIR/auth/$AUTH_ACCOUNT.json"
|
||||
[ -r "$AUTH_RESOLVED" ] && [ ! -L "$AUTH_RESOLVED" ] || { echo "agent: no mosaic-managed credential file for auth account '$AUTH_ACCOUNT': $AUTH_RESOLVED (see scripts/auth.sh accounts)" >&2; exit 4; }
|
||||
AUTH_PERMS="$(stat -c %a "$AUTH_RESOLVED")"
|
||||
[ "$AUTH_PERMS" = "600" ] || { echo "agent: auth account '$AUTH_ACCOUNT' file must be 0600 (got $AUTH_PERMS): $AUTH_RESOLVED" >&2; exit 4; }
|
||||
export PI_AUTH_FILE="$AUTH_RESOLVED"
|
||||
echo "agent: auth: account '$AUTH_ACCOUNT' -> $AUTH_RESOLVED" >&2
|
||||
fi
|
||||
|
||||
# Onboarding gate (M16): a TUI agent cannot launch without a user profile.
|
||||
# The onboarding wizard runs automatically here - the TTY is already yours.
|
||||
if [ ! -f "$MOSAIC_DEV_DIR/user/USER.md" ]; then
|
||||
|
||||
Reference in New Issue
Block a user