Files
10Backward/docs/architecture/runtime-changes.md
T

3.8 KiB

type, title, description, tags, timestamp
type title description tags timestamp
architecture Job 1089 Runtime Changes Container privilege separation, unified retry logging, configuration validation, and persistent data wiring introduced by the current implementation.
architecture
docker
retry
logging
configuration
2026-08-04T20:44:00Z

Overview

The current runtime keeps the container entrypoint and cron daemon as root while executing the Python bot as the unprivileged bot user. The pipeline owns one retry budget for Git synchronization and Mastodon publishing, and structured retry events include the operation and exception text. Configuration now validates required values before optional defaults are applied.

Wiring

Docker ENTRYPOINT /app/entrypoint.sh (root)
  -> validates environment and renders /etc/cron.d/tenbackward
  -> cron -f
  -> /usr/local/bin/run-bot.sh
     -> setpriv/su to bot
        -> python -m tenbackward
           -> load_config()
           -> _run_with_retry()
              -> _run_once()
                 -> ensure_repo(..., max_retries=0, logger=...)
                 -> match posts
                 -> PostedStore dedupe
                 -> publish_mastodon()
                 -> PostedStore.mark_posted_many()

The single ./data:/app/data Compose bind mount contains both the blog clone and posted.json; no file-level bind mount is used.

Retry and Logging Contract

MAX_RETRIES is interpreted as the maximum number of attempts, with at least one attempt when configured as zero. Backoff delays are 1, 2, 4, ... seconds between attempts. Git clone/pull retries are surfaced to the runner with operation labels (git clone or git pull), while publishing failures use mastodon post. Fatal configuration, local-repository, and publishing validation errors are not retried.

Retry events include an error field containing the exception message. log_event() sends structured fields through the same redaction path as other log helpers.

Configuration Validation

load_config() merges dotenv values and process environment values, validates required keys against that raw merged map, then applies defaults. MAX_RETRIES, BLOG_REPO_URL, and BLOG_DIR may use defaults; the required Mastodon, site, hashtag, prefix, schedule, and timezone values must be explicitly non-empty.

Key Files

Path Responsibility
/repo/Dockerfile Installs cron, Git, timezone data, and setpriv; leaves the final process root-capable for cron and owns /app/data by bot.
/repo/entrypoint.sh Validates environment, renders the daily cron entry, installs it as root, and starts foreground cron.
/repo/run-bot.sh Drops from root to bot using setpriv or su, then invokes the Python module.
/repo/docker-compose.yml Supplies environment values and mounts ./data at /app/data.
/repo/src/tenbackward/main.py Owns the unified retry loop and passes logger/retry controls into repository synchronization.
/repo/src/tenbackward/blog.py Clones or fast-forwards the blog and emits operation-specific retry events.
/repo/src/tenbackward/config.py Performs raw required-key validation and builds the typed configuration.
/repo/src/tenbackward/logging_setup.py Provides structured events, redaction, and JSON-per-line formatting.
/repo/tests/test_docker_artifacts.py Verifies container privilege and artifact wiring.
/repo/tests/test_config.py Verifies required-key validation and defaults.
/repo/tests/test_run_logging.py Verifies retry fields, attempt behavior, and state safety.

Related