Retire In-Repo env.map Fallback and Standardize ghclone on Central Environment Store¶
Status: Accepted (Amends ADR 0038, ADR 0050, and ADR 0057)
We completely remove legacy in-repo .secrets/env.map fallback decryption from shared/startup.sh, standardize the ghclone CLI helper to fetch and decrypt environment variables directly from env-store via pull-repo-env, and retire legacy decrypt-repo-env and encrypt-repo-env scripts from the shared image.
Context¶
Under ADR 0057, the Central Environment Store (env-store) was established as the authoritative secrets vault, shifting target repository secret decryption host-side in SandboxLauncher and injecting credentials into Modal containers via modal.Secret.from_dict() and VAULT_DOTENV_B64.
However, several legacy seams persisted:
1. Transitional Fallback in Sandbox Startup: shared/startup.sh still contained an in-container SOPS decryption loop inspecting $TARGET_DIR/.secrets/env.map.
2. ghclone Tied to In-Repo Manifests: The ghclone CLI helper checked exclusively for ${TARGET_DIR}/.secrets/env.map and invoked decrypt-repo-env, meaning repositories using env-store did not have their .env files populated upon ghclone.
3. Legacy CLI Utilities Staged in Container Images: Stale scripts decrypt-repo-env and encrypt-repo-env remained symlinked and maintained across shared/image.py and shared/startup.sh, despite being superseded by pull-repo-env and push-repo-env.
Decisions¶
- Complete Removal of In-Repo
.secrets/env.mapDecryption: - Remove the in-container SOPS decryption loop from
shared/startup.sh. - Sandbox provisioning relies exclusively on
VAULT_DOTENV_B64injected fromenv-store. -
Any legacy
.secrets/env.mapfiles present in target repositories are silently ignored without warnings or errors. -
Standardize
ghcloneonenv-store: - Update
scripts/ghcloneto delegate post-clone decryption topull-repo-env: -
Passing
--no-decryptor--skip-decrypttoghcloneskips secret retrieval. -
Graceful Non-Fatal Secret Retrieval (
--optional): - Add an
--optional(alias--ignore-missing) flag toscripts/pull_repo_env.py. -
When enabled,
pull-repo-envexits with status0and prints an informational notice if:- The repository has no secrets configured in
env-store(HTTP 404). - Decryption cannot proceed due to missing
AGE_PRIVATE_KEY/SOPS_AGE_KEY(e.g. running inside a standard sandbox withoutENABLE_SOPS=1). - GitHub credentials are not present.
- The repository has no secrets configured in
-
Retirement of Legacy CLI Utilities:
- Completely delete
scripts/decrypt_repo_env.py,scripts/encrypt_repo_env.py, their symlinks, and their test suites (tests/test_decrypt_repo_env.py,tests/test_encrypt_repo_env.py). -
Replace their entries in
shared/image.pyandshared/startup.shwithpush-repo-envandpull-repo-env. -
Documentation & Glossary Alignment:
- Update
GLOSSARY.md(Developer CLI Tooling Precedence) to listpush-repo-envandpull-repo-env. - Update
docs/architecture/secrets.mdto document the unifiedenv-storeworkflow for both sandbox provisioning andghclone.
Consequences¶
- Single Source of Truth: All target repository secrets live exclusively in
github.com/${GH_ORG_NAME}/env-store. - Consistent DX: Developers cloning via
ghclone(locally or inside sandboxes) automatically pull and decrypt their.envfile fromenv-store. - Public Repo Safety: Public open-source codebases require no
.secrets/directory or SOPS metadata in version control. - Clean Tooling: Stale
decrypt-repo-envandencrypt-repo-envutilities are removed from the image surface.