credentials.sh: gitea loader assumes one principal per host, so every gitea-mosaicstack wrapper fails with a valid token #1175
Open
opened 2026-08-12 22:04:10 +00:00 by Mos
·
0 comments
No Branch/Tag Specified
main
docs/1216-trunk-parameterization
next
docs/ia-merge-current
fix/869-lease-probe-timeout
feat/workspace-hygiene-tool-enforcement
feat/1080-pr-edit
fix/1182-fail-closed-launch
fix/1179-required-security-di
feat/p3-slice0-task5-chat-runtime-router-shaggy
feat/p3-slice0-task5-chat-runtime-router
feat/wf1-composition
feat/p3-slice0-task4-web-catalog-selection
feat/lease-promotion-and-harness-isolation
ci/provision-pi-runtime
feat/p3-slice0-task3-catalog-selection
feat/p3-slice0-task2-harness-registry
adopt/965-mos-ste-writing-standard
fix/991-comment-url-scheme-normalise
feat/wf2-bundle-migration
feat/wf4-plugin-acquisition
feat/wf5-refresh-safety
fix/1145-coord-di-compiled-boot
feat/p3-slice0-task1-harness-contracts
docs/webui-phase-p-structure
feat/1150-pi-goal-extension
feat/webui-p3-chat
fix/1146-ci-queue-purpose
fix/1138-conditional-federation
feat/webui-p2-data-auth
fix/gateway-runner-image
feat/webui-p1-vite-skeleton
fix/break-c-hooks-and-web-image
docs/webui-fleet-claude-bridge-plan
fix/wizard-gateway-failure
fix/ci-queue-wait-no-status
fix/next-node-gate
fix/mosaic-init-rce
greenfield/fomo-lin
fix/1099-pipefail-wake
fix/1099-pipefail-tests
fix/1099-pipefail-sweep
fix/framework-shell-portability
fix/1043-pane-git-identity
fix/1081-issue-close-silent-comment-failure
fix/1090-enrollment-wallclock-tolerance
feat/1082-tea-stale-token-diagnostic
fix/detect-platform-silent-128-outside-repo
feat/1050-install-state-machine-red-fixture
fix/pr-merge-message-field
feat/1051-mosaic-brain-installer
feat/1045-mosaic-cred
remediation/state
fix/1056-upgrade-rollback-control-race
fix/1019-ci-queue-timeout-harness
feat/rm-02-gate-registry
fix/rm-01-reproducible-checkout
remediation/mission-setup
fix/hygiene-inert-format-gate
fix/1019-queue-guard-stdin
feat/mos-ste-writing-standard
fix/1007-suite-hermeticity
feat/push-guard-null-case-verification
mos-comms-live
docs/heartbeat-framework-layering-ms-lead
feat/869-c4-version-coupling
feat/869-c2-install-ordering-guard
feat/869-c5-doctor-activation-check
feat/per-agent-gitea-identity
fix/875-belongs-case-insensitive-slug
fix/ci-queue-wait-404-branch-absent
feat/869-c1-activation-probe
feat/869-c3-broker-supervisor
fix/865-tea-cli-comment-invocation
feat/glpi-skills
fix/860-deflake-mutator-lease-gate
fix/850-detect-platform-port-normalization
fix/856-worktree-deps-preflight
fix/835-pr-review-approve-reject-comment-flag
fix/848-truthful-evidence
fix/812-pr-review-comment
fix/849-recovery-runtime-fixture-race
docs/758-ledger-m5-001-sync
feat/834-tc-server-side-doc
feat/833-constrained-recovery-command
feat/827-gate0-probe
governance/gate0-probe3-amendment
fix/795-codex-pr-diff
fix/795-ci-base-jq
fix/795-ci-base-git
feat/791-pr3-fleet-regen
feat/791-pr2-snapshot-restore
fix/807-glpi-206
fix/808-agent-send-false-sender
feat/791-upgrade-config-protection
feat/790-mosaic-yolo-claudex-pr2
feat/790-mosaic-yolo-claudex
feat/758-v1-v2-migrator
fix/766-exact-fleet-comms
test/758-reconciler-lifecycle-gates
docs/771-kbn101-db-role-split
test/758-example-profile-dispositions
feat/758-shared-role-resolution
feat/mos-logical-identity-fencing
feat/769-kbn100-unified-schema
docs/753-kbn010-threat-gate
feat/758-roster-v2-compiler
feat/756-official-discord-plugin
docs/758-fleet-config-management
fix/mos-option2-qualification-format
docs/issue-758-m0
docs/mos-option2-qualification
mos-comms
feat/tess-interaction-agent
fix/tess-docs-format
draft/mosaic-platform-prd
fix/installer-provider-gate-and-local-gateway-redis
release/mosaic-cli-0.0.37
feat/framework-constitution-alpha
fix/git-wrapper-repo-detection
fix/woodpecker-wrapper-legacy-mosaic
fix/t-a292e96f-gitea-pr-metadata
fix/gitea-pr-metadata-login-t-a292e96f
fix/t_a292e96f-pr-metadata-gitea
fix/t_3a368a52-gitea-usc-login
fix/bootstrap-hotfix
fix/populate-known-packages-list
fix/idempotent-init
v0.0.39-alpha
mosaic-v0.0.31
fed-v0.2.0-m2
fed-v0.1.0-m1
mosaic-v0.0.29
mosaic-v0.0.28
mosaic-v0.0.27
mosaic-v0.0.26
mosaic-v0.0.25
mosaic-v0.0.24
v0.2.0
v0.1.0
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#1175
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Symptom
Every
gitea-mosaicstackwrapper on this host fails with:ci-queue-wait.sh,pr-create.sh,pr-review.sh,issue-*.sh— the whole suite againstgit.mosaicstack.devis dead, which is worse than a wrapper being undiscoverable: gate 7requires the wrapper before any raw provider call, so the fail-closed posture leaves the
agent with no legal path at all and a strong incentive to reach for
curlanyway.Cause
tools/_lib/credentials.shresolves a flat key:but a host with more than one principal on the same Gitea stores them named, with a
pointer:
.gitea.mosaicstack.tokendoes not exist, so the loader exports an empty string and theguard reports a missing token. The credential is present and valid — verified by hand:
both principals return HTTP 200 on
/api/v1/userandpush=trueon the target repo.This is not a stale or revoked credential, and diagnosing it as one wastes a rotation.
Why it is a framework bug and not a config bug
The same file already handles exactly this shape correctly for two other services —
authentikresolves.authentik.${ak_instance}.token,woodpeckerresolves.woodpecker.${wp_instance}.tokenwith a documented legacy-flat fallback. Only the twogitea-*branches assume a single principal per host. The multi-principal layout is theone the fleet actually needs, because a seat must never borrow another seat's identity.
Proposed fix
In the
gitea-*branches, resolve in this order:GITEA_TOKENalready in the environment — unchanged, still wins.MOSAIC_GITEA_PRINCIPALif set — explicit beats implicit, and identity selectionshould be sayable out loud.
.gitea.<host>.default→.gitea.<host>.<that>.token..gitea.<host>.token— backward compatibility.the principal names, never pick one.
Step 5 matters on a host where the default login is an admin account: a loader that
silently picks a principal is making an authorisation decision on the agent's behalf.
Mirror
usernamealongsidetoken, since Gitea basic auth needs both and the wrapperscurrently have no way to learn it.
Also worth flagging separately
On the host where this was found,
gitea.mosaicstack.defaultpoints at a principal namedfor the other Gitea instance. Both happen to authenticate, so nothing failed loudly —
but a host-matched default is the thing an operator expects, and a cross-host default is
the sort of quiet mismatch that surfaces later as an unexplained permission error. That
is an operator-file question, not a framework change.
Repro
Given a credentials file with named principals under
gitea.mosaicstackand no flattokenkey: