Files

42 lines
2.3 KiB
Markdown

# The test sandbox is enforced via four-layer rules (FR1-FR4) — see the styleguide
## The 4-Layer Model
| Layer | Mechanism | Where | Default-on? |
|---|---|---|---|
| Layer 1 | Python runtime file-I/O guard (`sys.addaudithook`) | `tests/conftest.py:_sandbox_audit_hook` | Yes |
| Layer 2 | `isolate_workspace` autouse + `pyproject.toml --basetemp` | `tests/conftest.py` + `pyproject.toml` | Yes |
| Layer 3 | OS-level restricted-token PowerShell wrapper | `scripts/run_tests_sandboxed.ps1` | **Opt-in** |
| Layer 4 | Static audit script (CI gate) | `scripts/audit_test_sandbox_violations.py` | Yes (informational) / opt-in (`--strict`) |
Layer 1 + Layer 2 + Layer 4 are file-presence-on = enabled (delete the relevant file to disable). Layer 3 requires explicit invocation.
## The `--config` CLI Flag (replaces `SLOP_CONFIG`)
The historical `SLOP_CONFIG` env var has been removed from `src/paths.py`. The CLI flag `--config <path>` is now the ONLY supported mechanism for overriding the default `<project_root>/config.toml` location.
```bash
# Use the default <project_root>/config.toml
uv run python sloppy.py
# Override
uv run python sloppy.py --config /path/to/your/config.toml
```
`sloppy.py` calls `paths.set_config_override(Path(args.config).resolve())` AFTER `parse_args()` and BEFORE any `from src.gui_2 import App` import. This is the only way to override the config path in production.
## The `--basetemp` Rule
`pyproject.toml` sets `addopts = "--basetemp=tests/artifacts/_pytest_tmp"`. This redirects pytest's `tmp_path` and `tmp_path_factory` fixtures (which default to `%TEMP%\pytest-of-<user>\` on Windows) into `./tests/artifacts/`. This is what allows the Layer 1 allowlist to be a single rule: "anything under `./tests/` is allowed."
## Layer 1 Audit Hook Contract
`tests/conftest.py:_sandbox_audit_hook` is a `sys.addaudithook` callback. It fires on every `open()` call. Behavior:
- **Reads** (mode `r`, `rb`): pass through, no check
- **Writes** (mode contains `w`, `a`, `x`, `+`): check path
- **Allowed** if path resolves under:
- `<project_root>/tests/`
- Path contains `.pytest_cache`, `__pycache__`, `.coverage`, `.slop_cache`, or `.ruff_cache`
- Original path string starts with `\\.\` (Windows device namespace) or `/dev/` (Unix device namespace)
- **Blocked** otherwise: raises `RuntimeError("TEST_SANDBOX_VIOLATION: attempted to write to <path>...")`