docs(prd): add pipelock yaml contract
test / unit (pull_request) Successful in 31s
test / integration (pull_request) Successful in 40s

This commit is contained in:
2026-06-02 08:00:44 +00:00
committed by didericis
parent 3472e06efb
commit 47b75030ee
@@ -0,0 +1,106 @@
# PRD 0037: Pipelock YAML Render Contract
- **Status:** Draft
- **Author:** didericis-codex
- **Created:** 2026-06-02
- **Issue:** #130
## Summary
Lock down the contract between `pipelock_build_config` and
`pipelock_render_yaml` so hand-rendered pipelock YAML stays aligned with the
structured config bot-bottle builds. Keep the stdlib-only renderer, but add
shape validation and semantic tests for every supported section.
## Problem
`bot_bottle/pipelock.py` builds a structured dict and then renders a fixed YAML
shape by hand. This avoids a runtime YAML dependency, but it also means the
renderer directly indexes expected keys. If `pipelock_build_config` adds,
renames, or conditionalizes a section, rendering can fail at runtime or emit
YAML that no longer matches the config semantics.
Existing tests assert important rendered fragments, but they do not fully lock
the build/render contract or optional-section combinations. A mismatch here can
weaken DLP enforcement or break bottle launch after a future pipelock policy
change.
## Goals / Success Criteria
- Keep the renderer stdlib-only.
- Define the supported pipelock config shape in one place.
- Fail clearly when `pipelock_render_yaml` receives an unsupported or malformed
config shape.
- Add tests covering all supported sections:
- base allowlist and forward proxy.
- seed phrase detection toggle.
- DLP and request-body/header scanning.
- TLS interception and passthrough domains.
- SSRF IP allowlist.
- Add semantic tests that compare structured config values to rendered YAML
output without relying only on brittle substring assertions.
- Preserve current rendered YAML for existing configs unless a clearer failure
path requires an error message change.
## Non-goals
- No PyYAML or other runtime dependency.
- No change to pipelock policy defaults.
- No change to egress-to-pipelock topology.
- No change to pipelock image version or config schema beyond validation of the
shape bot-bottle already emits.
## Scope
In scope:
- `bot_bottle/pipelock.py` render helpers and validation.
- Unit tests in `tests/unit/test_pipelock_yaml.py` and related focused
pipelock tests.
- Small helper functions for typed access to config sections, if useful.
Out of scope:
- Launch/backend changes.
- Integration tests that start a real pipelock container.
- Changing the manifest schema for route-level pipelock policy.
## Design
Treat `pipelock_render_yaml` as a serializer for the narrow config shape
produced by `pipelock_build_config`, not as a generic YAML renderer. Before
rendering a section, validate that required keys exist with the expected
primitive/list/dict types. Missing or unsupported shapes should raise a clear
`ValueError` naming the section and key.
Tests should cover both normal output and failure cases. Because the project is
stdlib-only, semantic tests can use a small purpose-built parser for the exact
rendered shape or compare rendered lines to values from the structured config
through helper assertions. The goal is to detect drift between config dict and
YAML without adding a general YAML dependency.
Optional sections should be exercised in combinations:
- no TLS and no SSRF.
- TLS enabled with empty and non-empty passthrough domains.
- SSRF enabled with one or more IP/CIDR entries.
- all optional sections enabled together.
## Testing Strategy
- Extend `tests/unit/test_pipelock_yaml.py` with semantic assertions tying each
rendered section back to the config dict.
- Add malformed-config tests for missing required keys and wrong section types.
- Keep existing render fragment tests where they protect exact pipelock syntax.
Run:
- `python3 -m unittest tests.unit.test_pipelock_yaml`
- `python3 -m unittest tests.unit.test_pipelock_allowlist`
- `python3 -m unittest discover -s tests/unit`
## Open Questions
- Should malformed config errors be `ValueError`, matching current
`pipelock_build_config` validation, or a new internal exception type? Prefer
`ValueError` unless a caller needs to distinguish serializer errors.