safesight/docs/superpowers/specs/2026-04-19-config-management-minimal-loop-design.md

5.4 KiB

Config Management Minimal Loop Design

Purpose

Improve configuration management without returning to hand-maintained full JSON configs. The first implementation loop makes rendered configs traceable and lets the RK3588 agent report which config file is present and, when metadata is available, which config identity it represents.

This is intentionally smaller than the full backend management system. It creates the device-side facts that the backend can rely on later.

Current Context

The maintained media-server config source is the template/profile/overlay workflow:

  • Template: configs/templates/workshop_face_shoe_alarm.json
  • Device/site profile: configs/profiles/local_3588_test.json
  • Scenario overlays: configs/overlays/*.json
  • Generated runtime configs: configs/generated/*.json

The agent already exposes build metadata through UDP discovery, GET /v1/info, and GET /v1/versions. It also has older config/ui/* endpoints that generate configs from Go-embedded templates. Those endpoints remain supported, but this work should not expand the embedded-template model.

First-Loop Scope

  1. Add optional trace metadata to rendered configs.
  2. Add an agent read API that reports config path, hash, timestamps, metadata, and media-server process config path when available.
  3. Keep current GET /v1/config and PUT /v1/config behavior intact.
  4. Keep generated config files disposable and out of git.

Out of scope for this loop:

  • Full backend UI implementation.
  • Full profile/overlay package upload and server-side rendering in Go.
  • Hot reload guarantees for hardware-dependent media-server behavior.
  • Replacing existing config/ui/* endpoints.

Config Metadata Model

Rendered configs may include a top-level metadata object:

{
  "metadata": {
    "config_id": "local_3588_face_debug",
    "config_version": "20260419.001",
    "template": "workshop_face_shoe_alarm",
    "template_path": "configs/templates/workshop_face_shoe_alarm.json",
    "profile": "local_3588_test",
    "profile_path": "configs/profiles/local_3588_test.json",
    "overlays": [
      "face_debug"
    ],
    "overlay_paths": [
      "configs/overlays/face_debug.json"
    ],
    "rendered_by": "tools/render_config.py",
    "rendered_at": "2026-04-19T00:00:00Z"
  }
}

metadata is operational trace data. Media-server should ignore it if it only consumes global, queue, templates, instances, or graphs.

config_hash should not be embedded into the JSON in this loop because hashing a file that contains its own hash creates awkward circular semantics. The agent computes and reports the file hash instead.

Render Tool Behavior

tools/render_config.py gains optional flags:

  • --config-id
  • --config-version
  • --rendered-at
  • --metadata-json

When any metadata flag is provided, the script writes top-level metadata. Without those flags, existing output remains compatible except for stable implementation details needed by tests.

--metadata-json accepts a JSON object and is merged first. CLI fields override same-named metadata keys so automation can supply defaults and still stamp a specific config ID/version.

Agent API

Add:

GET /v1/config/status

Response shape:

{
  "ok": true,
  "config_path": "/etc/rk3588sys/config.json",
  "exists": true,
  "size": 12345,
  "mtime_ms": 1776528000000,
  "sha256": "hex",
  "metadata": {
    "config_id": "local_3588_face_debug",
    "config_version": "20260419.001"
  },
  "last_good_path": "/etc/rk3588sys/config.json.last_good.json",
  "last_good": {
    "exists": true,
    "size": 12340,
    "mtime_ms": 1776520000000,
    "sha256": "hex",
    "metadata": {}
  },
  "media_server": {
    "supported": true,
    "running": true,
    "pid": 1234,
    "config_path": "/etc/rk3588sys/config.json",
    "started_at_ms": 1776528005000
  }
}

If the config file is missing, the endpoint returns 200 with exists:false and no hash instead of 404. This makes the backend device-detail page simpler: missing config is status, not transport failure.

Backend-Visible Field Boundaries

User-facing configurable fields should be profile/overlay parameters such as:

  • RTSP/video source
  • device/site/channel identity
  • backend token/API URLs
  • MinIO endpoint, bucket, and credentials
  • face gallery path when deployment layout requires it
  • selected overlays for debug, sensitivity, or production quiet mode
  • carefully selected alarm thresholds and cooldowns

Internal fields stay hidden unless an engineering mode later exposes them:

  • DAG edges and internal node IDs
  • shared state keys
  • gallery embedding dimension
  • model input/output tensor assumptions
  • CPU affinity and low-level queue tuning
  • tracker and plugin glue parameters that can break cross-node contracts

Validation

Local code-level validation:

  • Python unit tests or focused script checks for metadata rendering.
  • Go tests for GET /v1/config/status response behavior.
  • git diff --check.
  • go test ./... in agent if changes touch agent code.

RK3588 device-side validation:

  • Pull latest code on device.
  • Render a config with metadata.
  • Start or restart media-server with that generated config.
  • Query GET /v1/config/status, GET /v1/info, and GET /v1/versions.
  • Confirm /tmp/media-server.log shows the expected runtime config path and no startup regression.

Device-side validation is required before claiming hardware/runtime behavior is verified.