103 lines
3.7 KiB
Markdown
103 lines
3.7 KiB
Markdown
# PRD 0038: smolmachines Env Contract and Secret-Safe Injection
|
|
|
|
- **Status:** Active
|
|
- **Author:** didericis-codex
|
|
- **Created:** 2026-06-02
|
|
- **Issue:** #135
|
|
|
|
## Summary
|
|
|
|
Make smolmachines env handling match Docker's contract: resolve manifest env
|
|
entries through `resolve_env()`, keep secret and interpolated values out of
|
|
host argv, and document or enforce an explicit env contract for the backend.
|
|
|
|
## Problem
|
|
|
|
`bot_bottle/backend/smolmachines/prepare.py` builds the guest env from
|
|
`bottle.env` directly, bypassing `resolve_env()`. Entries like `?prompt` and
|
|
`${HOST_VAR}` can reach the guest literally rather than being prompted or
|
|
resolved. In contrast, Docker resolves env through `resolve_env()` before
|
|
writing a mode-600 env file.
|
|
|
|
`smolmachines/smolvm.py` renders env as `-e KEY=VALUE` on `smolvm machine
|
|
create` argv, and `SmolmachinesBottle.agent_argv` / `exec` prepend
|
|
`env KEY=VALUE …` onto the `smolvm machine exec` argv. Any literal or resolved
|
|
secret value is therefore visible in the host process table.
|
|
|
|
The two backends have no shared env contract document. Divergence will silently
|
|
widen as new manifest env features are added.
|
|
|
|
## Goals / Success Criteria
|
|
|
|
- Manifest env entries are resolved through `resolve_env()` before being
|
|
injected into the smolmachines guest, matching Docker behaviour.
|
|
- No manifest env value (literal or resolved) appears on host argv during
|
|
machine creation or exec.
|
|
- Define and document an explicit smolmachines env contract covering literals,
|
|
`?prompt` secrets, and `${HOST_VAR}` interpolations.
|
|
- Unit tests cover: literal passthrough, prompted-secret resolution,
|
|
host-var interpolation, and the no-argv-leak invariant.
|
|
|
|
## Non-goals
|
|
|
|
- No changes to the Docker env path.
|
|
- No changes to manifest schema or `resolve_env()` itself.
|
|
- No changes to smolmachines networking or mount handling.
|
|
- No new runtime dependencies.
|
|
|
|
## Scope
|
|
|
|
In scope:
|
|
|
|
- `bot_bottle/backend/smolmachines/prepare.py` env resolution.
|
|
- `bot_bottle/backend/smolmachines/smolvm.py` machine-create argv.
|
|
- `bot_bottle/backend/smolmachines/bottle.py` `agent_argv` / `exec` env
|
|
injection.
|
|
- `bot_bottle/env.py` if helper changes are needed to support the smolmachines
|
|
path.
|
|
- Unit tests in `tests/unit/` covering the above.
|
|
|
|
Out of scope:
|
|
|
|
- Integration tests that start a live smolmachines VM.
|
|
- Docker backend changes.
|
|
- Dashboard or CLI changes.
|
|
|
|
## Design
|
|
|
|
Run smolmachines env through `resolve_env()` at prepare time, exactly as Docker
|
|
does. After resolution, inject env into the guest through a mechanism that does
|
|
not expose values on host argv — for example by writing a mode-600 env file
|
|
into the machine's state directory and loading it at exec time, or by passing
|
|
env through `smolvm`'s stdin if the tool supports it.
|
|
|
|
If `smolvm` provides no stdin or env-file injection path, document this as a
|
|
known limitation and at minimum move env values behind a per-invocation
|
|
tmpfile rather than inline argv.
|
|
|
|
The env contract for smolmachines should mirror Docker's:
|
|
|
|
- Literals: passed as-is after resolution.
|
|
- `?prompt` entries: prompted at prepare time; resolved value injected, never
|
|
on argv.
|
|
- `${HOST_VAR}` entries: interpolated from the operator's env at prepare time;
|
|
resolved value injected, never on argv.
|
|
|
|
## Testing Strategy
|
|
|
|
- Unit tests for `prepare.py` asserting `resolve_env()` is called and that
|
|
resolution results are used rather than raw `bottle.env` values.
|
|
- Unit tests for `smolvm.py` machine-create argv asserting no env value appears
|
|
inline.
|
|
- Unit tests for `bottle.py` exec path asserting the same argv invariant.
|
|
|
|
Run:
|
|
|
|
- `python3 -m unittest tests.unit.test_smolmachines_prepare`
|
|
- `python3 -m unittest discover -s tests/unit`
|
|
|
|
## Open Questions
|
|
|
|
- Does `smolvm machine create` support an env-file flag or stdin injection that
|
|
avoids `-e KEY=VALUE` argv?
|