Files

HAN Message Safety v2

Production-oriented internal FastAPI service for deterministic text, URL and quarantined-file safety checks. PostgreSQL is the durable source of truth for idempotency, tasks, leases, fencing, caches, audit and immutable config snapshots. Redis is intentionally optional and may only accelerate hot-cache/rate/wakeup paths.

Local verification

Python 3.12 is required. These commands do not start services:

python -m pip install -e ".[dev]"
pytest
ruff check .
message-safety-config validate app/artifacts/seed-config.yaml

Migrations and config administration require MESSAGE_SAFETY_CONFIG_ADMIN_DATABASE_URL_FILE. Runtime secrets are accepted only through *_FILE; the entrypoint rejects missing/empty files without printing their values.

alembic upgrade head
message-safety-config create app/artifacts/seed-config.yaml --version 1 --actor migration
message-safety-config activate --version 1 --approved-by security-owner

Deployment boundary

docker-compose.fragment.yml is an include fragment for the root VM2 Compose. It publishes no host port, runs API and worker as UID 10001 with a read-only filesystem, drops all capabilities, and mounts only service-specific secret files plus the broker Unix socket /run/han-kesl/scan.sock into the worker. The root project owns networks/secrets and the root-owned emergency mode file. KESL 12.4 standalone and its root-owned fail-closed broker are host services, not Compose services; clamd and freshclam are absent from Compose.

The broker invokes the fixed host command kesl-control --scan-file --action Inform. A clean result may continue to allow, an infected result denies, and scanner errors, unknown output, timeouts or a stale KESL database remain retryable and eventually return 503 rather than allowing content. Runtime records scanner_engine=kesl; signatures_version is the hash of KESL version plus database date. KESL database updates run hourly under the operator KESL runbook.

External release gates

The following cannot be proven by repository-only tests and must remain fail-closed until the target environment verifies them:

  • Selectel S3 supports version-specific GetObject, signed conditional ETag behavior, bucket versioning, checksum metadata, virtual-host addressing and a read-only IAM policy without list/write/delete.
  • KESL version/database date is supplied through the broker to readiness and task cache keys; hourly update, stale-database alarms and clean/EICAR/malformed corpora pass on VM2.
  • The broker is a custom integration: exact kesl-control output/exit semantics, socket permissions, cleanup and throughput must pass gates on the target VM2 with KESL 12.4.
  • HEIF native decoding and PDF parser sandbox resource limits pass the approved corpus. The in-process detector is bounded by 5 MiB and validates active/encrypted PDF markers, but OS-level CPU/memory/wall-time isolation must be enforced by the worker container and target runtime.
  • Managed PostgreSQL role grants prove runtime cannot migrate or activate config, while the config-admin role can; migration constraint, concurrent activation, lease and fencing tests run against PostgreSQL (not SQLite).
  • Trusted resolver, DNS rebinding corpus, S3 canary and worker heartbeat are wired into production readiness probes.
  • Image dependencies are resolved to a reviewed lock/SBOM and the final image is pinned by digest in the root Compose release manifest.
  • Target load gates (10 text checks/s, 2 file checks/s, 100 pending tasks, five worker slots) and privacy/log redaction are verified in production-like infrastructure.

No HTTP fetch, redirect following or rendering of user-provided URLs exists in this service.