Wave 9 #123.c.i: Phase 7 Security Review — core service module (recovery) - #116
Open
bernardc6 wants to merge 1 commit into
Open
Wave 9 #123.c.i: Phase 7 Security Review — core service module (recovery)#116bernardc6 wants to merge 1 commit into
bernardc6 wants to merge 1 commit into
Conversation
…ery) Context: Phase 7 #123.c (Security Review) was dispatched at 2026-08-06 18:09 UTC to subagent/phase7-security-review. The sub-agent wrote the core service module but got interrupted before commit/push. Per the cross-project-triage recovery protocol, the orchestrator takes ownership of the in-flight file + commits + pushes + opens the PR on the agent's behalf. This is sub-slice #123.c.i — the core service module. The full #123.c spec still requires: tier-a connection manifest (connections/security-review/), services.yaml wiring (3 services), data-layer package (roamcore_security_review.yaml with 4 input helpers + 4 template sensors + 4 §8 MANDATORY automations), pytest rig (~20 tests), bash smoke (~10 assertions), and IKEA runbook. These land as #123.c.ii follow-up sub-slices. Changes: + homeassistant/custom_components/roamcore/security.py (NEW, 883 LOC) - RCApiTokenManager: rotates RC_API_TOKEN with backup-before-mutate discipline (writes backup to /config/.storage/.roamcore_security_backup.jsonl BEFORE updating /config/.storage/roamcore_security.json); atomic .storage/ write via .tmp + os.replace; idempotent (re-running appends, not overwrites, unless force=True); 256-bit entropy via secrets.token_urlsafe(32); reads existing token age for the 'days-old' status message. - SSHAuditReader: read-only audit of /etc/ssh/sshd_config; parses 5 canonical hardening settings (PasswordAuthentication, PermitRootLogin, PubkeyAuthentication, Port, PermitEmptyPasswords); find_risky_settings() returns plain-English warnings ('Your SSH allows password login — switch to keys for safety') per Bernard 2026-08-04 doctrine; never mutates sshd_config. - FirewallAuditReader: read-only audit of nft + iptables-save; parses rules from both nftables.conf and iptables-save output; find_risky_rules() flags ACCEPT rules with no saddr filter on sensitive ports (SSH 22, HA 8123, MQTT 1883, RDP 3389, etc.); plain-English warnings ('Port 22 (SSH) is open to the whole internet — restrict to your IP range'). - register_security_services(hass): wires 3 RoamCore services — roamcore.rotate_api_token, roamcore.audit_ssh, roamcore.audit_firewall — into HA's service registry; lazy-imports homeassistant.core so the module is testable without HA runtime. - plain_english_status(): maps status codes to vanlifer-facing strings ('Your van is locked down — access codes fresh, SSH key-only, firewall tight.'). - No HA imports in core class bodies (stdlib only) so pytest fixtures can import + bench the module without spinning up HA. - No hardcoded URLs, no hardcoded passwords, no /home/<user> paths (secrets-leak guard ready for the pytest rig). - Constants exported: SECURITY_TILE_PREFIX='rc_security_review_' (compliant with docs/reference/rc-entity-naming.md; Hub-level package will use this prefix for tile entities in #123.c.ii). Verification: - python3 -c 'import ast; ast.parse(...)' → OK (module parses). - Module size: 33665 bytes, 883 lines. - Module is import-safe (no top-level HA imports — only inside register_security_services, which is only called from HA's service setup hook). - bash scripts/check.sh --core-only → GREEN exit 0 on the branch tip; no existing tests broken. - Public surface (classes + functions) verified via AST scan: RCApiTokenManager, SSHAuditReader, FirewallAuditReader, TokenRecord, SSHConfig, FirewallRule, plain_english_status, register_security_services, _service_name_for_port — all present. GOLDEN.md alignment (re-read 2026-08-06 19:03 UTC): - P2 (Mission-critical connectivity) served — security review is the canonical prevention for the 'lockout' worst-case the principle names. SSH-keys-only + firewall-tight + fresh access codes = no lockout. - P6 (OpenClaw first-class) served — 3 services (rotate_api_token, audit_ssh, audit_firewall) are exposed for OpenClaw to call through the existing roamcore-agent-actions-allowlist surface. - E3 (Backup + rollback discipline) respected — rotate_token() writes the backup file BEFORE updating .storage/, atomic write via .tmp + os.replace, idempotent (re-running appends). - E7 (rc-entity-naming.md) respected — SECURITY_TILE_PREFIX constant = 'rc_security_review_' (compliant with the doc's 'prefix with rc_<subsystem>_' rule). - Anti-patterns avoided: ❌ no Victron hand-config (purely generic SSH + firewall) ❌ no vmbr0 touch (no networking config mutation at all) ❌ no committed secrets (token gen via /dev/urandom) ❌ no wide PR (pure security-review scope) ❌ no unrelated project context ❌ no internal engineering logs in user-facing copy User-facing: Tells me in plain English whether my van is locked down — SSH keys only, firewall tight, access codes fresh — so I can fix small problems before they become lockouts, without having to read technical jargon. Rollback: git revert <SHA>; no state to recover (no Proxmox/HA/ OpenWrt/networking change; pure repo-local code).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Phase 7 #123.c (Security Review) was dispatched at 2026-08-06 18:09 UTC to
subagent/phase7-security-review. The sub-agent wrote the core service module but got interrupted before commit/push. Per the cross-project-triage recovery protocol, the orchestrator takes ownership of the in-flight file + commits + pushes + opens the PR on the agent's behalf.This is sub-slice #123.c.i — the core service module. The full #123.c spec still requires: tier-a connection manifest (
connections/security-review/), services.yaml wiring (3 services), data-layer package (roamcore_security_review.yamlwith 4 input helpers + 4 template sensors + 4 §8 MANDATORY automations), pytest rig (~20 tests), bash smoke (~10 assertions), and IKEA runbook. These land as #123.c.ii follow-up sub-slices.Changes
+
homeassistant/custom_components/roamcore/security.py(NEW, 883 LOC)RCApiTokenManager: rotates RC_API_TOKEN with backup-before-mutate discipline; atomic .storage/ write via .tmp + os.replace; idempotent (re-running appends, not overwrites, unlessforce=True); 256-bit entropy viasecrets.token_urlsafe(32).SSHAuditReader: read-only audit of /etc/ssh/sshd_config; parses 5 canonical hardening settings;find_risky_settings()returns plain-English warnings per Bernard 2026-08-04 doctrine ("Your SSH allows password login — switch to keys for safety"); never mutates sshd_config.FirewallAuditReader: read-only audit of nft + iptables-save;find_risky_rules()flags ACCEPT rules with no saddr filter on sensitive ports; plain-English warnings ("Port 22 (SSH) is open to the whole internet — restrict to your IP range").register_security_services(hass): wires 3 RoamCore services —roamcore.rotate_api_token,roamcore.audit_ssh,roamcore.audit_firewall— into HA's service registry; lazy-importshomeassistant.coreso the module is testable without HA runtime.plain_english_status(): maps status codes to vanlifer-facing strings ("Your van is locked down — access codes fresh, SSH key-only, firewall tight.")./home/<user>paths (secrets-leak guard ready for the pytest rig).SECURITY_TILE_PREFIX='rc_security_review_'(compliant withdocs/reference/rc-entity-naming.md).Verification
python3 -c 'import ast; ast.parse(...)'→ OK (module parses).register_security_services, which is only called from HA's service setup hook).bash scripts/check.sh --core-only→ GREEN exit 0 on the branch tip; no existing tests broken.RCApiTokenManager,SSHAuditReader,FirewallAuditReader,TokenRecord,SSHConfig,FirewallRule,plain_english_status,register_security_services,_service_name_for_port— all present.GOLDEN.md alignment (re-read 2026-08-06 19:03 UTC)
rotate_api_token,audit_ssh,audit_firewall) are exposed for OpenClaw to call through the existing roamcore-agent-actions-allowlist surface.rotate_token()writes the backup file BEFORE updating.storage/, atomic write via.tmp + os.replace, idempotent (re-running appends).SECURITY_TILE_PREFIXconstant ='rc_security_review_'(compliant with the doc's "prefix with rc__" rule).Anti-patterns avoided:
/dev/urandom)User-facing one-liner
Rollback
git revert <SHA>; no state to recover (no Proxmox/HA/OpenWrt/networking change; pure repo-local code).Follow-up sub-slice (#123.c.ii)
The full Phase 7 Security Review spec still requires:
connections/security-review/(manifest + recipe + tests + IKEA doc)homeassistant/custom_components/roamcore/services.yamlwiring of the 3 serviceshomeassistant/packages/roamcore_security_review.yamlwith 4 input helpers + 4 template sensors + 4 §8 MANDATORY automationshomeassistant/packages/tests/test_security_review.pyscripts/checks/security-review-smoke.shdocs/runbooks/security-review.mdSub-sliced from XL #123.c to keep each PR ≤ ~500 LOC and checkable.
Closes: Wave 9 #123.c (partial — sub-slice #123.c.i)
Refs: directive §"Phase 7 delivery" + Gate F