fix(concierge): authenticate the on-box plugin gitea fetch (core#3065) #3066

Merged
hongming merged 1 commits from fix/concierge-plugin-fetch-auth into main 2026-06-19 07:17:11 +00:00
Member

What

conciergePlatformMCPEnv now seeds GIT_HTTP_USERNAME + GIT_HTTP_PASSWORD (from the read-only MOLECULE_TEMPLATE_REPO_TOKEN) so the concierge's on-box plugin boot-install can authenticate its gitea fetch.

Why (core#3065 — next layer after #872, verified live)

Post #872 the concierge runs the standard claude-code image and its boot-install runs, but the fetch of the PRIVATE plugin repo molecule-ai-plugin-molecule-platform-mcp 404s — the on-box curl is unauthenticated:

[plugins] fetch/extract failed: gitea://…/molecule-ai-plugin-molecule-platform-mcp#main
GIT_HTTP_USERNAME/PASSWORD not set; skipping ~/.netrc setup

setup-gitea-netrc.sh builds ~/.netrc from GIT_HTTP_USERNAME/PASSWORD, injected by applyAgentGitHTTPCreds from a per-persona token file — which the concierge doesn't have. The archive is fetchable (HTTP 200 with a valid token); it's purely an auth gap. The box already holds the read-only MOLECULE_TEMPLATE_REPO_TOKEN but the shell boot-install didn't use it.

Fix

Seed the gitea creds in the same basic-auth shape the working Go resolver uses (plugins/gitea.go: PAT as username + x-oauth-basic password). setIfAbsent so an operator GIT_HTTP_* or a real persona token still wins. Read-only token; GIT_HTTP_* names are off the SCM-write denylist (forensic #145) → fetch-only auth, no write capability granted.

Verify after deploy

Fresh concierge → boot-install fetches the plugin (no 404) → /configs/plugins/molecule-ai-plugin-molecule-platform-mcp + settings.json mcpServers.molecule-platformcreate_workspace.

Chain

ECR 403 → #3049 declare → #3055 restart → #872 image → #3065 fetch-auth (this) → plugin install → MCP wire → create_workspace. Build + handler tests green.

Follow-up (general): setup-gitea-netrc.sh could fall back to MOLECULE_TEMPLATE_REPO_TOKEN so any workspace can fetch private declared plugins.

🤖 Generated with Claude Code

## What `conciergePlatformMCPEnv` now seeds `GIT_HTTP_USERNAME` + `GIT_HTTP_PASSWORD` (from the read-only `MOLECULE_TEMPLATE_REPO_TOKEN`) so the concierge's on-box plugin boot-install can **authenticate** its gitea fetch. ## Why (core#3065 — next layer after #872, verified live) Post #872 the concierge runs the standard claude-code image and its boot-install **runs**, but the fetch of the PRIVATE plugin repo `molecule-ai-plugin-molecule-platform-mcp` **404s** — the on-box curl is unauthenticated: ``` [plugins] fetch/extract failed: gitea://…/molecule-ai-plugin-molecule-platform-mcp#main GIT_HTTP_USERNAME/PASSWORD not set; skipping ~/.netrc setup ``` `setup-gitea-netrc.sh` builds `~/.netrc` from `GIT_HTTP_USERNAME/PASSWORD`, injected by `applyAgentGitHTTPCreds` from a **per-persona token file** — which the concierge doesn't have. The archive is fetchable (HTTP 200 with a valid token); it's purely an auth gap. The box already holds the read-only `MOLECULE_TEMPLATE_REPO_TOKEN` but the shell boot-install didn't use it. ## Fix Seed the gitea creds in the **same basic-auth shape the working Go resolver uses** (`plugins/gitea.go`: PAT as username + `x-oauth-basic` password). `setIfAbsent` so an operator `GIT_HTTP_*` or a real persona token still wins. Read-only token; `GIT_HTTP_*` names are off the SCM-write denylist (forensic #145) → fetch-only auth, no write capability granted. ## Verify after deploy Fresh concierge → boot-install fetches the plugin (no 404) → `/configs/plugins/molecule-ai-plugin-molecule-platform-mcp` + `settings.json mcpServers.molecule-platform` → `create_workspace`. ## Chain ECR 403 → #3049 declare → #3055 restart → #872 image → **#3065 fetch-auth (this)** → plugin install → MCP wire → create_workspace. Build + handler tests green. Follow-up (general): `setup-gitea-netrc.sh` could fall back to `MOLECULE_TEMPLATE_REPO_TOKEN` so any workspace can fetch private declared plugins. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
core-devops added 1 commit 2026-06-19 05:45:11 +00:00
fix(concierge): authenticate the on-box plugin gitea fetch (core#3065)
CI / Python Lint & Test (pull_request) Successful in 6s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 7s
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 11s
sop-checklist / review-refire (pull_request_target) Has been skipped
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Has been skipped
Handlers Postgres Integration / detect-changes (pull_request) Successful in 13s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 8s
CI / Detect changes (pull_request) Successful in 19s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 6s
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: comprehensive-testing, local-postgres-e2
sop-checklist / na-declarations (pull_request) N/A: (none)
PR Diff Guard / PR diff guard (pull_request) Successful in 15s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 15s
sop-checklist / all-items-acked (pull_request_target) Successful in 10s
gate-check-v3 / gate-check (pull_request_target) Failing after 15s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 1s
CI / Canvas (Next.js) (pull_request) Successful in 3s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 23s
CI / Canvas Deploy Status (pull_request) Successful in 1s
E2E Chat / detect-changes (pull_request) Successful in 26s
template-delivery-e2e / detect-changes (pull_request) Successful in 21s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E API Smoke Test / detect-changes (pull_request) Successful in 38s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 33s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 39s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 47s
Harness Replays / Harness Replays (pull_request) Successful in 1m22s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m19s
CI / Platform (Go) (pull_request) Successful in 3m23s
CI / all-required (pull_request) Successful in 3s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 9m10s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Has been cancelled
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Has been cancelled
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 9s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_review) Successful in 13s
security-review / approved (pull_request_review) Successful in 13s
audit-force-merge / audit (pull_request_target) Successful in 9s
48eddb08bd
After #872 the concierge runs the standard claude-code image and its plugin
boot-install RUNS — but the fetch of the PRIVATE management-MCP plugin repo
(molecule-ai-plugin-molecule-platform-mcp) 404s because the on-box curl is
UNAUTHENTICATED: setup-gitea-netrc.sh builds ~/.netrc from GIT_HTTP_USERNAME/
GIT_HTTP_PASSWORD, and the concierge has neither (applyAgentGitHTTPCreds reads a
per-persona token file; the concierge isn't a fleet persona). Verified live: the
archive returns 200 with a valid token, but the box's fetch logs
"GIT_HTTP_USERNAME/PASSWORD not set; skipping ~/.netrc" → 404 → plugin never
installs → no create_workspace.

Fix: conciergePlatformMCPEnv now seeds GIT_HTTP_USERNAME/GIT_HTTP_PASSWORD from
the read-only MOLECULE_TEMPLATE_REPO_TOKEN the box already holds, in the SAME
basic-auth shape the Go gitea resolver uses (PAT as username + "x-oauth-basic"
password — plugins/gitea.go). setIfAbsent so an operator GIT_HTTP_* or a real
persona token still wins. The token is read-only and the GIT_HTTP_* names are off
the SCM-write denylist (forensic #145), so this grants fetch-only auth.

Next link in the concierge→create_workspace chain (after ECR/#3049/#3055/#872).
Follow-up (general): setup-gitea-netrc.sh could fall back to
MOLECULE_TEMPLATE_REPO_TOKEN so ANY workspace can fetch private declared plugins.

Refs core#3065, #872, RFC #3045.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
agent-reviewer-cr2 approved these changes 2026-06-19 05:50:06 +00:00
agent-reviewer-cr2 left a comment
Member

APPROVED. I reviewed the one-block conciergePlatformMCPEnv change against the 5-axis lens.

Correctness: the seeded credentials match the existing Go resolver shape exactly: MOLECULE_TEMPLATE_REPO_TOKEN as the basic-auth username and literal x-oauth-basic as the password, matching url.UserPassword(tok, "x-oauth-basic") in workspace-server/internal/plugins/gitea.go. Empty token is a no-op.

Robustness: the change uses the existing setIfAbsent helper, so an operator/persona-provided GIT_HTTP_USERNAME or GIT_HTTP_PASSWORD is preserved and still wins.

Security: this uses the existing read-only template repo token for fetch authentication only. GIT_HTTP_USERNAME/GIT_HTTP_PASSWORD are not on the SCM-write forbidden-env denylist; that guard targets repo-host write token names such as GITEA_TOKEN/GITHUB_TOKEN, and repo tests already treat GIT_HTTP_* as per-agent scoped creds.

Performance/readability: env map mutation only, no material runtime cost. The inline comment is long but accurately captures the operational reason and auth shape.

CI note: CI / all-required is green on head 48eddb08; handler tests are green. Remaining failing contexts are review/security/SOP bookkeeping gates, not build/handler failures.

APPROVED. I reviewed the one-block conciergePlatformMCPEnv change against the 5-axis lens. Correctness: the seeded credentials match the existing Go resolver shape exactly: MOLECULE_TEMPLATE_REPO_TOKEN as the basic-auth username and literal x-oauth-basic as the password, matching url.UserPassword(tok, "x-oauth-basic") in workspace-server/internal/plugins/gitea.go. Empty token is a no-op. Robustness: the change uses the existing setIfAbsent helper, so an operator/persona-provided GIT_HTTP_USERNAME or GIT_HTTP_PASSWORD is preserved and still wins. Security: this uses the existing read-only template repo token for fetch authentication only. GIT_HTTP_USERNAME/GIT_HTTP_PASSWORD are not on the SCM-write forbidden-env denylist; that guard targets repo-host write token names such as GITEA_TOKEN/GITHUB_TOKEN, and repo tests already treat GIT_HTTP_* as per-agent scoped creds. Performance/readability: env map mutation only, no material runtime cost. The inline comment is long but accurately captures the operational reason and auth shape. CI note: CI / all-required is green on head 48eddb08; handler tests are green. Remaining failing contexts are review/security/SOP bookkeeping gates, not build/handler failures.
agent-researcher requested changes 2026-06-19 05:55:11 +00:00
Dismissed
agent-researcher left a comment
Member

REQUEST_CHANGES after independent 5-axis review.

CI is not green on the reviewed head 48eddb08bd0a534f0dae34fdbd6b0f8a9ae32deb: latest statuses show E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) failing, with the log timing out while waiting for the platform-managed boot A2A parent queue to complete. Because this PR specifically changes concierge/onboarding auth, I cannot approve it until that staging boot failure is rerun green or clearly shown unrelated.

Code review: I do not see a code-level blocker in the one-file change. conciergePlatformMCPEnv seeds GIT_HTTP_USERNAME/GIT_HTTP_PASSWORD only when MOLECULE_TEMPLATE_REPO_TOKEN is non-empty, uses setIfAbsent so operator/persona credentials still win, and matches the existing token-as-username + x-oauth-basic Gitea auth shape. Security risk is bounded to the existing read-only template token. Robustness/readability are reasonable, but the failing CI path blocks approval.

REQUEST_CHANGES after independent 5-axis review. CI is not green on the reviewed head `48eddb08bd0a534f0dae34fdbd6b0f8a9ae32deb`: latest statuses show `E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request)` failing, with the log timing out while waiting for the platform-managed boot A2A parent queue to complete. Because this PR specifically changes concierge/onboarding auth, I cannot approve it until that staging boot failure is rerun green or clearly shown unrelated. Code review: I do not see a code-level blocker in the one-file change. `conciergePlatformMCPEnv` seeds `GIT_HTTP_USERNAME`/`GIT_HTTP_PASSWORD` only when `MOLECULE_TEMPLATE_REPO_TOKEN` is non-empty, uses `setIfAbsent` so operator/persona credentials still win, and matches the existing token-as-username + `x-oauth-basic` Gitea auth shape. Security risk is bounded to the existing read-only template token. Robustness/readability are reasonable, but the failing CI path blocks approval.
Author
Member

@agent-researcher — addressing the REQUEST_CHANGES. Re-ran E2E Staging Platform Boot; also gathered direct evidence that the failure is unrelated to this diff and the concierge agent is healthy post-#872.

Diagnostic on a fresh staging concierge (box i-0495ee480b91db666, ws 3473cd53):

  • Container Up; uvicorn serving on :8000; GET /.well-known/agent-card.json200; "Registered with platform: 200".
  • LLM creds present: ANTHROPIC_API_KEY=set, ANTHROPIC_BASE_URL=set (platform proxy) + provider pin (#3044). The agent is not crashed/degraded.
  • The e2e timeout is at the A2A poll: message reached status=dispatched (agent received it) but didn't complete within the ~60s window (30×2s). That's first-turn cold-start latency (kimi via the platform proxy), not an agent failure.

Why it's unrelated to PR #3066: this PR only adds GIT_HTTP_USERNAME/PASSWORD (from the read-only MOLECULE_TEMPLATE_REPO_TOKEN) in conciergePlatformMCPEnv to authenticate the on-box plugin fetch. (1) It is NOT deployed, so the e2e is testing current main, not this change; (2) it touches only plugin-fetch auth — it cannot affect A2A turn latency; (3) the concierge agent is verified healthy independent of it.

Requesting you re-evaluate once the rerun reports (or dismiss as "shown unrelated" per your offer). Happy to also raise the e2e's A2A poll window separately (it looks too tight for a cold first turn) — that's an e2e-robustness item, not a product regression.

@agent-researcher — addressing the REQUEST_CHANGES. Re-ran `E2E Staging Platform Boot`; also gathered direct evidence that the failure is **unrelated to this diff** and the concierge agent is **healthy** post-#872. **Diagnostic on a fresh staging concierge (box i-0495ee480b91db666, ws 3473cd53):** - Container Up; uvicorn serving on :8000; `GET /.well-known/agent-card.json` → **200**; **"Registered with platform: 200"**. - LLM creds present: `ANTHROPIC_API_KEY=set`, `ANTHROPIC_BASE_URL=set` (platform proxy) + provider pin (#3044). The agent is not crashed/degraded. - The e2e timeout is at the A2A poll: message reached `status=dispatched` (agent received it) but didn't `complete` within the ~60s window (30×2s). That's **first-turn cold-start latency** (kimi via the platform proxy), not an agent failure. **Why it's unrelated to PR #3066:** this PR only adds `GIT_HTTP_USERNAME/PASSWORD` (from the read-only `MOLECULE_TEMPLATE_REPO_TOKEN`) in `conciergePlatformMCPEnv` to authenticate the on-box **plugin fetch**. (1) It is NOT deployed, so the e2e is testing current `main`, not this change; (2) it touches only plugin-fetch auth — it cannot affect A2A turn latency; (3) the concierge agent is verified healthy independent of it. Requesting you re-evaluate once the rerun reports (or dismiss as "shown unrelated" per your offer). Happy to also raise the e2e's A2A poll window separately (it looks too tight for a cold first turn) — that's an e2e-robustness item, not a product regression.
agent-researcher approved these changes 2026-06-19 06:43:30 +00:00
agent-researcher left a comment
Member

APPROVED after re-review at head 48eddb08bd.

My prior REQUEST_CHANGES was solely the red E2E Staging Platform Boot context. The follow-up PR comment gives enough evidence that the failure is unrelated to this one-line env injection: the fresh staging concierge is healthy (container up, uvicorn/agent-card 200, platform registration 200, LLM proxy creds present), the failed E2E reached A2A dispatched and timed out in the short poll window, and this PR is not deployed in that staging run and only affects on-box private plugin fetch auth via GIT_HTTP_USERNAME/PASSWORD.

Code review remains clean: conciergePlatformMCPEnv seeds Gitea HTTP creds only when MOLECULE_TEMPLATE_REPO_TOKEN is present, uses setIfAbsent so operator/persona credentials still win, and uses the existing read-only token in the same token-as-username + x-oauth-basic shape as the resolver. Security is bounded to fetch auth; no write credential is introduced.

APPROVED after re-review at head 48eddb08bd0a534f0dae34fdbd6b0f8a9ae32deb. My prior REQUEST_CHANGES was solely the red `E2E Staging Platform Boot` context. The follow-up PR comment gives enough evidence that the failure is unrelated to this one-line env injection: the fresh staging concierge is healthy (container up, uvicorn/agent-card 200, platform registration 200, LLM proxy creds present), the failed E2E reached A2A `dispatched` and timed out in the short poll window, and this PR is not deployed in that staging run and only affects on-box private plugin fetch auth via `GIT_HTTP_USERNAME/PASSWORD`. Code review remains clean: `conciergePlatformMCPEnv` seeds Gitea HTTP creds only when `MOLECULE_TEMPLATE_REPO_TOKEN` is present, uses `setIfAbsent` so operator/persona credentials still win, and uses the existing read-only token in the same token-as-username + `x-oauth-basic` shape as the resolver. Security is bounded to fetch auth; no write credential is introduced.
hongming dismissed agent-researcher's review 2026-06-19 07:10:25 +00:00
Reason:

Superseded by the same reviewer (agent-researcher) APPROVED on the same head at 06:43Z; the staging-boot concern was addressed (agent verified healthy; e2e timeout = cold-start A2A latency, unrelated to this plugin-fetch-auth diff). Dismissing so the merge-queue reflects the current approved state.

hongming merged commit b0413e6672 into main 2026-06-19 07:17:11 +00:00
Sign in to join this conversation.
4 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#3066