docs: add PRD 0038
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
# PRD 0038: smolmachines Env Contract and Secret-Safe Injection
|
||||
|
||||
- **Status:** Draft
|
||||
- **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?
|
||||
Reference in New Issue
Block a user