WP-0002 — Correctness and Operational Completeness (priority: high) T1: TTL max enforcement per ActorType T2: Stale cert cleanup command (warden cleanup) T3: Outgoing signatures log (warden log) WP-0003 — Test Coverage and Code Quality (priority: medium) T1: VaultCA tests T2: LocalCA.generate_keypair tests T3: CLI tests (test_cli.py) T4: Real ssh-keygen integration test T5: File permissions enforcement (mode 600) T6: warden status --state-dir override Both registered in Custodian State Hub under ops-warden repo (74df727e). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.7 KiB
id, type, title, domain, repo, status, owner, topic_slug, created, updated, state_hub_workstream_id
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| WARDEN-WP-0003 | workplan | OpsWarden Test Coverage and Code Quality | custodian | ops-warden | active | Bernd | custodian | 2026-05-15 | 2026-05-15 | cb2bbf3c-848a-4af6-ba64-8361e64cd4d7 |
WARDEN-WP-0003 — Test Coverage and Code Quality
Scope: Close the test coverage gaps left after WARDEN-WP-0001: VaultCA has
zero tests, generate_keypair is untested, no CLI tests exist, and no real
ssh-keygen integration test was written. Also fix file permission enforcement
(security) and add --state-dir override to warden status (usability).
Out of scope: Functional behaviour changes (WARDEN-WP-0002), Vault cluster setup, host-side tooling.
Goal
After this workplan:
- VaultCA has a full unit test suite covering success, auth failure, network failure, and role-map misconfiguration.
generate_keypairhas direct unit tests alongside the existingsigntests.- A
tests/test_cli.pycovers every command's exit codes and output shape. - A
tests/test_integration.pymarked@pytest.mark.integrationexercisesLocalCA.sign()against a realssh-keygenwithout any mocking. - Cert and key files written by warden are always mode 600; a scorecard check flags world-readable files.
warden status --state-dir <path>works without awarden.yaml.
Reference Documents
| Document | Location |
|---|---|
| WARDEN-WP-0001 | workplans/WARDEN-WP-0001-initial-implementation.md |
| WARDEN-WP-0002 | workplans/WARDEN-WP-0002-correctness-and-completeness.md |
| CertCommandInterface | wiki/CertCommandInterface.md |
Design Decisions
Integration tests: separate marker, not separate directory
Use @pytest.mark.integration and skip when ssh-keygen is not in PATH. Tests
live in tests/test_integration.py. The unit suite (uv run pytest) excludes
integration tests via pytest.ini_options addopts = "-m 'not integration'";
uv run pytest -m integration runs them explicitly. This keeps CI fast while
making the real-ssh-keygen path easy to invoke manually.
File permissions: at write time, not at read time
os.chmod(path, 0o600) is called immediately after each path.write_text() or
shutil.copy2() that writes a key or cert. No deferred or scheduled chmod. The
scorecard check catches files that were written by older versions of warden or by
external tools.
warden status --state-dir: config bypass, not config optional
When --state-dir is provided, skip load_config() entirely — don't try to
load a partial config. This makes the flag useful on remote machines that have
received a cert via ops-bridge but have no warden installation.
Tasks
T1 — VaultCA tests
id: WARDEN-WP-0003-T1
state_hub_task_id: eff074ce-c027-4df5-8006-0990296592ac
status: todo
priority: high
- Create
tests/test_vault.py - Test
VaultCA.sign()success: mockhttpx.postreturning a validsigned_key; assertCertRecordfields; assert cert file written to state_dir - Test HTTP 403:
httpx.HTTPStatusError→CAErrorwith status code in message - Test unreachable Vault:
httpx.RequestError→CAErrorwith fallback hint - Test missing
VAULT_TOKEN:_token()raisesCAErrorbefore HTTP call - Test missing role in
role_map:CAErrorbefore HTTP call - Test missing pubkey file:
CAErrorbefore HTTP call
T2 — LocalCA.generate_keypair tests
id: WARDEN-WP-0003-T2
state_hub_task_id: ddfe5331-0a3b-4783-bdf4-f5ebcdf7965c
status: todo
priority: medium
- Add
TestGenerateKeypairclass totests/test_ca.py - Test success: mock
subprocess.run; assert privkey and pubkey paths returned - Test ssh-keygen called with
-t ed25519,-N "",-C actor_name - Test existing files are unlinked before generation (write dummy files first)
- Test
CAErrorraised on non-zero ssh-keygen exit code - Test output files land in
state_dir/keys/
T3 — CLI tests
id: WARDEN-WP-0003-T3
state_hub_task_id: 040ce3a1-0efb-4816-a2d9-357162dd1612
status: todo
priority: high
- Create
tests/test_cli.pyusingtyper.testing.CliRunner warden sign: exits 0 and stdout is cert text (mock CA); exits 1 on unknown actor; exits 1 on config errorwarden issue: exits 1 on vault backend; exits 0 on local backend (mock CA)warden status: exits 0 and prints "no cert" message when state_dir empty; exits 1 when cert is expired (mockparse_cert_metadata)warden scorecard: exits 0 on clean inventory + empty state_dir; exits 1 when a check failswarden inventory add / list / remove: round-trip via tmp inventory filewarden log: exits 0 with empty output when no log;--jsonis valid JSON (after WARDEN-WP-0002 T3 adds the log command)warden cleanup --dry-run: exits 0, no files deleted (after WARDEN-WP-0002 T2 adds cleanup)
T4 — Real ssh-keygen integration test
id: WARDEN-WP-0003-T4
state_hub_task_id: 434fb008-103f-410c-85fd-e77b33e61fe4
status: todo
priority: medium
- Create
tests/test_integration.py - Mark all tests
@pytest.mark.integration - Add
pytest.ini_optionstopyproject.toml:addopts = "-m 'not integration'"so unit suite skips them by default - Test
LocalCA.sign()end-to-end: generate a real CA keypair and actor keypair via subprocess ssh-keygen in tmp_path; callLocalCA.sign(); assertCertRecord.valid_before > datetime.now(utc); assert cert file exists; assertparse_cert_metadata()succeeds on it without mocking - Skip test if
shutil.which("ssh-keygen") is None - Document in README:
uv run pytest -m integrationto run real-CA tests
T5 — File permissions enforcement (mode 600)
id: WARDEN-WP-0003-T5
state_hub_task_id: ac146fe6-d1fd-4186-91bd-6f098de72449
status: todo
priority: medium
ca.pyLocalCA.sign(): callos.chmod(dest, 0o600)aftershutil.copy2ca.pyLocalCA.generate_keypair(): callos.chmod(privkey, 0o600)andos.chmod(pubkey, 0o644)after generationvault.pyVaultCA.sign(): callos.chmod(dest, 0o600)afterdest.write_textscorecard.py: addcheck_file_permissions(state_dir)— flag any*-cert.puborkeys/*file wherestat().st_mode & 0o044 != 0- Add
check_file_permissionstorun_scorecard() - Update
test_ca.py: assertos.chmodcalled with correct mode after sign and generate_keypair (patch os.chmod or check stat on actual files in tmp_path)
T6 — warden status --state-dir override
id: WARDEN-WP-0003-T6
state_hub_task_id: 1c9f1987-7b11-43c1-a5e3-c2fd8d1c1589
status: todo
priority: low
cli.pystatus(): addstate_dir_override: Annotated[Optional[Path], typer.Option("--state-dir")] = None- When
--state-diris provided: use it directly, skip_load_cfg()entirely - When absent: load config as today
- Add test in
test_cli.py: invokewarden status --state-dir <tmp_path>without a config file; assert exit 0
Acceptance Criteria
uv run pytestruns unit suite only; all pass; VaultCA and generate_keypair covereduv run pytest -m integrationsucceeds (requires ssh-keygen in PATH)test_cli.pycovers all commands; no mocked subprocess in CLI tests where avoidable (use tmp inventory files and mocked CA)ls -la ~/.local/state/warden/*.pubshows mode 600 for newly signed certs- Scorecard
file_permissionscheck passes on a clean state dir; fails on a world-readable cert warden status --state-dir /tmp/some-dirruns without awarden.yaml- All lints pass:
uv run ruff check .