--- title: "1.7.0 — MojoSec host sensor, and nodes that fetch their own releases" description: "Adds MojoSec — a settings-free host sensor for dedicated EC2 nodes that turns journald, nginx and file-integrity signals into bounded batches for the incident system. Edge nodes now fetch promoted web app releases from S3 themselves, verified per file. Also fixes a bug that made every edge converge…" date: "2026-08-09" tags: ["release"] canonical: "https://django-mojo.sitesmojo.com/changelog/1-7-0/" --- Adds MojoSec — a settings-free host sensor for dedicated EC2 nodes that turns journald, nginx and file-integrity signals into bounded batches for the incident system. Edge nodes now fetch promoted web app releases from S3 themselves, verified per file. Also fixes a bug that made every edge converge fail on a standard Linux node. ### Breaking - Release manifests are capped at 1 GiB total (`EDGE_RELEASE_MAX_BYTES`). A larger bundle is refused at registration; a file-count cap alone did not bound bytes, and every node fetches a release onto its own disk. ### Added - **MojoSec host sensor** (`mojo.mojosec`) — reads a deliberately narrow signal set (SSH logins and failures, sudo, PAM sessions, systemd/kernel and OOM activity, exploit-path probes, 401/403 denials, 5xx, targeted file integrity), aggregates it, and delivers bounded batches. It never bans an address locally — the incident system stays the policy and enforcement authority. Sudo arguments are never persisted. - `POST /api/incident/mojosec/batch` — machine-facing gzip receiver on the strict `mojosec.batch` v1 contract, with a durable handler outbox and replay. - New permission `mojosec_ingest`. Each installation authenticates with its own API key carrying a protected profile that must name the same sensor. - Operator-only learning loop: append-only detector feedback and offline policy evaluation, global permissions only, API keys rejected. - Edge nodes fetch promoted release bytes from S3 themselves, verified per file against the manifest, incremental, using the instance role. - A web app's vhost may sit on a domain owned by its group or an ancestor, so one domain and one wildcard certificate can carry several teams. - New settings: `MOJOSEC_RECEIPT_RETENTION_DAYS`, `MOJOSEC_LEARNING_EVALUATION_RETENTION_DAYS`, `EDGE_RELEASE_FETCH_TIMEOUT`, `EDGE_RELEASE_FETCH_BUDGET`, `EDGE_RELEASE_MAX_BYTES`. `EDGE_KEEP_RELEASES` is now enforced. ### Changed - An unfetchable web app release degrades that vhost only — it keeps serving its previous release, or goes dark if it never served — instead of aborting the whole install. The converge retries until it heals. ### Fixed - **The staged nginx pre-filter failed on every standard Linux node.** `nginx -t` binds every listen it parses, and an unprivileged process gets EACCES on 443/80, which is fatal — so every converge died at the pre-filter and reverted. It passed development only because macOS allows unprivileged low-port binds. The pre-filter now validates a listen-remapped staging tree. - Certificate-material failures are retried on the next converge instead of leaving the vhost excluded until something unrelated moved. - Generation pruning no longer fails a job whose install had succeeded. ### Security - Models carrying an AI-denial policy are refused by generic model-query tools and cannot be attached to assistant context. - All MojoSec learning models are denied to AI/model-query tools. ### Upgrade notes - MojoSec is opt-in and inert until enrolled: it needs a per-installation API key, a root service install, and its own config file. See the sensor documentation and the enrollment/canary runbook. - The staged-nginx fix introduces `EDGE_STAGED_HTTP_PORT` and `EDGE_STAGED_HTTPS_PORT` (61080/61443). Make sure nothing else on the node uses them.