|
Some checks are pending
Block internal-flavored paths / Block forbidden paths (pull_request) Blocked by required conditions
CI / Detect changes (pull_request) Blocked by required conditions
CI / Platform (Go) (pull_request) Blocked by required conditions
CI / Canvas (Next.js) (pull_request) Blocked by required conditions
CI / Shellcheck (E2E scripts) (pull_request) Blocked by required conditions
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
CI / Python Lint & Test (pull_request) Blocked by required conditions
CodeQL / Analyze (${{ matrix.language }}) (go) (pull_request) Blocked by required conditions
CodeQL / Analyze (${{ matrix.language }}) (javascript-typescript) (pull_request) Blocked by required conditions
CodeQL / Analyze (${{ matrix.language }}) (python) (pull_request) Blocked by required conditions
E2E API Smoke Test / detect-changes (pull_request) Blocked by required conditions
E2E API Smoke Test / E2E API Smoke Test (pull_request) Blocked by required conditions
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Blocked by required conditions
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Blocked by required conditions
Handlers Postgres Integration / detect-changes (pull_request) Blocked by required conditions
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Blocked by required conditions
Runtime PR-Built Compatibility / detect-changes (pull_request) Blocked by required conditions
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Blocked by required conditions
Secret scan / Scan diff for credential-shaped strings (pull_request) Blocked by required conditions
Adds an operator escape-hatch fallback to molecule-git-token-helper.sh: if
the platform /github-installation-token endpoint is unreachable AND no
GITHUB_TOKEN/GH_TOKEN env var is set, the helper now reads a static PAT
from ${CONFIGS_DIR:-/configs}/.github-token before exiting with "all token
sources exhausted".
# Why
The 2026-05-08 incident exposed a hard dependency: every workspace's git
and gh CLI operations route through the platform's GitHub App
installation-token endpoint. When that endpoint started returning 500
("token refresh failed", root-caused to missing GITHUB_APP_ID env vars on
the platform side), every workspace lost git+gh auth simultaneously and
there was no operator escape-hatch — the helper exhausted its sources
and exited 1, breaking PR review, merge, and clone across the org.
This change lets infra drop a manually-issued PAT into /configs/.github-token
(agent-writable per /entrypoint.sh chown -R agent:agent /configs) to keep
git ops running while the platform endpoint is being repaired.
# Properties
- Pure additive: no existing fallback step is altered. The chain becomes
cache > API > env > static > exit 1. Existing env-var users see no
behavior change (env still wins over static).
- Static path NEVER writes to the cache. When the API recovers, the
next call sees a stale-cache miss and fills the cache via the API
path immediately — no 50-min stale-cache stickiness on the workaround.
- Both _fetch_token (git credential helper path) and _refresh_gh
(gh CLI / daemon path) gain the fallback; otherwise git would work
but gh would still be unauthenticated.
- Empty static file is rejected (no false-positive). File missing
is rejected. Whitespace stripped via tr -d '[:space:]'.
- Preserves PR #1552's umask 077 hardening verbatim in _write_cache
and _refresh_gh's ~/.gh_token write — only the api_token variable
reference is renamed to chosen_token in the post-source-selection
write paths.
# Tests run on the rebased file
1. bash -n syntax check — clean.
2. Static-token path with API broken + env unset → static path fires,
correct token output, correct log message.
3. 'get' action via static path → emits proper git-credential-protocol
(username=x-access-token + password=<token>).
4. Empty static file → rejected, returns "all token sources exhausted",
exit 1 (no regression).
5. (Implicit by structure) env_token still takes precedence over
static_token — env-var fallback block is unchanged and runs first.
# Rollout
Applying this change in the canonical repo lands the fix permanently
once a workspace-image rebuild pulls it into /app/scripts/. For the
in-incident window, operators can also drop the patched script at
~/molecule-git-token-helper.sh and re-point credential.https://github.com.helper
in ~/.gitconfig — works without root and without /app/scripts writes.
# Origin
Branch + design originally drafted by fullstack-engineer
(commit d4ed8768 in their workspace, unable to push due to the same
auth incident). Structural approval from core-platform-lead. Rebased
onto upstream main and pushed via my fork because every other agent
in the mesh was also blocked from pushing.
Co-Authored-By: fullstack-engineer <fullstack-engineer@agents.moleculesai.app>
Co-Authored-By: core-platform-lead <core-platform-lead@agents.moleculesai.app>
|
||
|---|---|---|
| .. | ||
| adapters | ||
| builtin_tools | ||
| lib | ||
| molecule_audit | ||
| platform_tools | ||
| plugins_registry | ||
| policies | ||
| scripts | ||
| skill_loader | ||
| tests | ||
| .coveragerc | ||
| a2a_cli.py | ||
| a2a_client.py | ||
| a2a_executor.py | ||
| a2a_mcp_server.py | ||
| a2a_response.py | ||
| a2a_tools_delegation.py | ||
| a2a_tools_inbox.py | ||
| a2a_tools_memory.py | ||
| a2a_tools_messaging.py | ||
| a2a_tools_rbac.py | ||
| a2a_tools.py | ||
| adapter_base.py | ||
| agent.py | ||
| agents_md.py | ||
| boot_routes.py | ||
| build-all.sh | ||
| card_helpers.py | ||
| config.py | ||
| configs_dir.py | ||
| consolidation.py | ||
| coordinator.py | ||
| Dockerfile | ||
| entrypoint.sh | ||
| event_log.py | ||
| events.py | ||
| executor_helpers.py | ||
| heartbeat.py | ||
| inbox_uploads.py | ||
| inbox.py | ||
| initial_prompt.py | ||
| internal_chat_uploads.py | ||
| internal_file_read.py | ||
| main.py | ||
| mcp_cli.py | ||
| mcp_doctor.py | ||
| mcp_heartbeat.py | ||
| mcp_inbox_pollers.py | ||
| mcp_workspace_resolver.py | ||
| molecule_ai_status.py | ||
| not_configured_handler.py | ||
| platform_auth.py | ||
| platform_inbound_auth.py | ||
| plugins.py | ||
| preflight.py | ||
| prompt.py | ||
| pytest.ini | ||
| rebuild-runtime-images.sh | ||
| requirements.txt | ||
| runtime_wedge.py | ||
| secret_redactor.py | ||
| shared_runtime.py | ||
| smoke_mode.py | ||
| transcript_auth.py | ||
| watcher.py | ||