refactor: daemon collectors, thin webui proxies, pure config reads
- move state collectors from lib/state.py to daemon/collectors/ (7 modules, registration side-effect; daemon/server.py imports the package before the first populate()) - webui/api: new daemon_route() decorator factory in common.py collapses the try/except daemon-proxy boilerplate in all 8 blueprints (rules/params/body/transform keep responses identical) - firewall: interface-coverage invariant — config is the source of truth for zone interfaces (absent key = empty, no hands-off zones); pure validate_coverage() enforced at save (400) and apply (409, force: true overrides), top-level `unmanaged` exemption - lib: get_config() reads are now pure (no dir creation or writes); new lib/bootstrap.py creates runtime dirs and persists the one-shot nginx legacy migration at daemon start, after system_import (lib.nginx.migrate_config_file) - lib/common: compute_pending() apply-bookkeeping helper - daemon: emit_and_refresh() handler helper; refresh_state(bump=) so /status/refresh no longer bumps versions (poll/mutation only) - acme: move --log last so acme.sh never treats a real arg as the log-file argument - docs: AGENTS.md, config.md, state-model.md, api.md updated; HARDEN.md dropped (plan implemented); apply-confirm force wording Tests: 917 passed; ruff check + format clean.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
"""Daemon-startup filesystem bootstrap.
|
||||
|
||||
Runs once at daemon startup, after the system-config import and before the
|
||||
first state collection. Creates the runtime directories subsystems
|
||||
read/write and persists the one-shot nginx legacy-format migration.
|
||||
|
||||
Config *files* are deliberately NOT created here: ``get_config`` reads are
|
||||
pure and return in-memory defaults, and the system-config import must see
|
||||
absent files in order to adopt live system state on first start. Files are
|
||||
materialized on the first ``save_config`` (or by the import itself).
|
||||
"""
|
||||
|
||||
from lib import dnsmasq, firewall, network, nginx, wireguard
|
||||
from lib.common import ensure_dirs
|
||||
|
||||
__all__ = ["bootstrap"]
|
||||
|
||||
|
||||
def bootstrap() -> None:
|
||||
"""Create runtime directories and persist the one-shot nginx migration.
|
||||
|
||||
Idempotent — existing directories are left untouched and the nginx
|
||||
migration only rewrites the on-disk file when it actually changes.
|
||||
"""
|
||||
ensure_dirs(
|
||||
dnsmasq.CONFIG_DIR,
|
||||
dnsmasq.DATA_DIR,
|
||||
dnsmasq.FRAGMENTS_DIR,
|
||||
firewall.CONFIG_DIR,
|
||||
firewall.DATA_DIR,
|
||||
network.CONFIG_DIR,
|
||||
network.DATA_DIR,
|
||||
nginx.CONFIG_DIR,
|
||||
nginx.SITES_DIR,
|
||||
wireguard.CONFIG_PATH.parent,
|
||||
)
|
||||
# One-shot legacy-format migration for the nginx config (see
|
||||
# ``lib.nginx.get_config``). Runs here, at startup, so read paths stay
|
||||
# side-effect free.
|
||||
nginx.migrate_config_file()
|
||||
Reference in New Issue
Block a user