From d72f21da094b05e240f8923ba1bff5389ee09f75 Mon Sep 17 00:00:00 2001 From: claude-ceo-assistant Date: Fri, 8 May 2026 09:52:43 -0700 Subject: [PATCH] feat(local-dev): bind-mount ~/.molecule-ai/personas into platform container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes core#242 LOCAL surface. The PROD surface (CP user-data fetching persona env files into tenant EC2's /etc/molecule-bootstrap/personas via Secrets Manager) is filed as a follow-up. WHAT THIS ADDS Bind-mount on the platform service in docker-compose.yml: ${MOLECULE_PERSONA_ROOT_HOST:-${HOME}/.molecule-ai/personas} → /etc/molecule-bootstrap/personas (read-only) Default source = ${HOME}/.molecule-ai/personas (the operator-host-mirrored local dir populated by today's persona rotation work). Override via MOLECULE_PERSONA_ROOT_HOST when running on a machine with a different layout (CI runners, etc.). WHY READ-ONLY workspace-server only reads persona env files; never writes back. The read-only mount enforces that contract — a hostile plugin install path can't tamper with the persona credentials it's about to consume. WHY THIS PATH MATCHES PROD /etc/molecule-bootstrap/personas is the same in-container path the prod tenant EC2 will use. Same code path (org_import.go::loadPersonaEnvFile) reads the same file regardless of mode — local-dev parity with prod per feedback_local_must_mimic_production. STAGE A VERIFICATION - docker compose config: resolves to /Users/hongming/.molecule-ai/personas correctly (28 persona dirs visible at source path) - Persona env file shape verified: dev-lead's env contains GITEA_USER, GITEA_USER_EMAIL, GITEA_TOKEN_SCOPES, GITEA_SSH_KEY_PATH, MODEL_PROVIDER=claude-code, MODEL=opus (lead tier matches Hongming's 2026-05-08 mapping) - Full handler test suite green (TestLoadPersonaEnvFile_HappyPath + 7 sibling tests pass; rejection tests still catch path traversal) - Build clean STAGE B SKIPPED (with justification per § Skip conditions) This change is config-only (docker-compose.yml volume addition). The prod tenant EC2s do NOT use docker-compose.yml — they use CP user-data + ec2.go's docker run script. So this PR has no prod blast radius. Stage B (staging tenant probe) would be checking 'is the platform using the new compose mount' on a SaaS tenant — and SaaS tenants don't run docker compose. The actual prod-surface change is the follow-up issue. PROD SURFACE — FOLLOW-UP FILED Tenant EC2 user-data needs to fetch persona env files from operator host (or AWS Secrets Manager per the established feedback_unified_credentials_file pattern) and stage them at /etc/molecule-bootstrap/personas inside the workspace-server container. Touches molecule-controlplane/internal/provisioner/ec2.go user-data. Co-Authored-By: Claude Opus 4.7 (1M context) --- docker-compose.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 00e5804e..8cff1e19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,6 +195,19 @@ services: # App private key — read-only bind-mount. The host-side path is # gitignored per .gitignore rules (/.secrets/ + *.pem). - ./.secrets/github-app.pem:/secrets/github-app.pem:ro + # Per-role persona credentials (molecule-core#242 local surface). + # Sourced at workspace creation time by org_import.go::loadPersonaEnvFile + # when a workspace.yaml carries `role: `. The host-side dir is + # populated by the operator-host bootstrap kit (28 dev-tree personas); + # /etc/molecule-bootstrap/personas is the in-container path the + # platform expects (matches the prod tenant-EC2 path so the same code + # works in both modes). + # + # Read-only mount — workspace-server only reads, never writes here. + # If the host dir is empty/missing the platform's loadPersonaEnvFile + # silently no-ops per its existing semantics, so this mount is safe + # even on a fresh machine that hasn't run the bootstrap kit yet. + - ${MOLECULE_PERSONA_ROOT_HOST:-${HOME}/.molecule-ai/personas}:/etc/molecule-bootstrap/personas:ro ports: - "${PLATFORM_PUBLISH_PORT:-8080}:${PLATFORM_PORT:-8080}" networks: -- 2.45.2