CADENCE — Product Release Document

What "v1 launch" means, how the signed feed is published, the versioning/support policy, and the dependency punch-list of everything required to launch that cannot be fully done in an overnight build. Plans, not promises — no real accounts are wired tonight.

1. What v1 is (release scope)

**v1 = the free, source-available Advisory Client + a live, signed two-module feed (Proxmox/Ceph

  • Nextcloud), plus the paid feed subscription on top.** Concretely, a customer can:

    1. Install the client appliance (single Rust binary / container) in their infra.

    2. Point it at the feed URL (or an internal air-gap mirror) and the shipped public key.

    3. Connect ≥1 inventory adapter (Proxmox API, Nextcloud occ, or generic) — local only.

    4. See per-asset verdicts (install / hold / wait-for-patch / eol / blocked), cross-product ordering requirements, CVE highlights, and overdue service reminders — in a read-only UI.

    5. Get notified by email and/or a generic webhook when verdicts change.

In v1, out of scope (deferred, per mission §3): write-back to customer systems, the mobile mass-alarm app, vuln-scanner ingestion, the update-integrity hash UX, and multi-tenant SaaS feed hosting. The Compliance/air-gap tier is a packaging + contract on the same artifact, not new code.

Build status going into launch prep: the full MVP loop is built and tested offline (189 tests) and e2e-verified over real HTTP + a real SMTP wire. As of run #3 the appliance is a continuously-refreshing daemon (CADENCE_REFRESH_INTERVAL) with notify-on-change over both real channels (webhook and SMTP email, multi-channel, with retry); live signed-feed pull + fail-closed verify; four inventory adapters (incl. the real HttpGetter); optional dashboard Basic auth; a feed-builder lint that catches authoring mistakes pre-sign; and a tamper-evident, hash-chained decision audit trail (dashboard badge + GET /decisions.json export) — the concrete NIS2/compliance hook. Four feed modules ship (PostgreSQL proves a new stack needs zero engine code). Deploy artifacts (Dockerfile + compose + docs/deploy.md) are drafted + runtime-verified. What remains for launch: real curated feed content (M10 — the operating discipline), verifying the Docker build in a Docker-capable env, and the go-to-market dependencies below (see ttm.md).

2. The signed-feed publishing process (the operational heart)

This is the recurring release activity — it happens far more often than a code release.

author advisories (YAML, in feed-sample/-style module dirs)
  → feed-builder build  --feed <dir> --feed-version YYYY.MM.DD   # validate + hash → manifest.yaml
  → feed-builder verify --feed <dir> --public-key <pub>          # operator self-check (dry-run)
  → feed-builder sign   --feed <dir> --secret-key <signing.key>  # detached ed25519 → manifest.yaml.sig
  → publish the directory (manifest.yaml + .sig + module files) to the feed host/CDN
  → mirrors (customer air-gap) rsync the directory; clients pull + verify on their schedule

Cadence: the feed version is calendar-style (2026.06.22). Publish on a predictable beat (e.g. weekly), plus out-of-band for urgent verdicts (a critical "hold" or a security-driven install-urgent). The authoring cadence is the product — see ttm.md for the 3—​8h/week operating cost.

Key custody: the ed25519 secret key never touches customer infra and is never committed (.gitignore + signing.key written 0600 by keygen). v1 keeps it offline on the operator’s machine; the roadmap moves signing onto the Nitrokey 3C hardware fleet (PGP/smartcard path noted in DECISIONS.md D003). Key rotation = ship a new public key with a client update and dual-sign during the overlap window.

3. Versioning & support policy

  • Feed version: YYYY.MM.DD (date of publication). Advisories carry their own effective/expires window, so the client always evaluates the currently effective set.

  • Schema version: the feed format is versioned separately; the client tolerates unknown verified files (forward-compat — a newer feed can ship content an older client ignores) but fails closed on signature/hash/parse errors. Breaking schema changes get a major bump and a client-compatibility note.

  • Client version: semver. Source-available; security issues in the appliance are disclosed and patched on a published timeline (relevant under CRA — see market-research.md §4).

  • Support: Community = best-effort/community. Pro = email support. MSP/Compliance = priority advisory latency SLA + direct channel. The value customers pay for is advisory freshness and correctness, so the support promise is mostly about feed cadence, not code tickets.

4. Dependency punch-list (what launch needs that tonight can’t finish)

Each marked [have seam / need real account / need decision].

Dependency Status Note

Feed hosting / CDN

need real account

Static file host (object storage + CDN, or a plain web server). The feed is just signed static files, so this is cheap — even GitHub Pages/S3+CloudFront works.

Air-gap mirror guide

have seam

It’s rsync/static copy of a directory; document it. No code needed. The live client already writes the pulled feed into a cache dir that is a complete, re-verifiable mirror (CADENCE_FEED_CACHE) — point a customer’s mirror at it.

Signing-key custody (hardware)

need decision

v1: offline key file. Roadmap: Nitrokey 3C PGP signing. Decide rotation policy before first paid customer.

Transactional email (notifications)

need real account (transport DONE)

The real SMTP transport is built (lettre, rustls, STARTTLS) and e2e-verified against a local sink; only a real mailbox/relay account + STARTTLS verification to a hosted provider remain.

Webhook delivery

DONE

Real ureq JSON POST wired (CADENCE_NOTIFY_WEBHOOK_URL); e2e-verified against a local sink. Customers point it at Slack/Teams/PagerDuty.

Notify-on-change daemon

DONE

CADENCE_REFRESH_INTERVAL re-evaluates on a timer and delivers only changed alerts (incl. due-reminder alerts), with retry; e2e-verified over a real pulled feed.

Compliance audit trail

DONE

Tamper-evident hash-chained decision log + dashboard "HASH CHAIN INTACT" badge + auth-gated GET /decisions.json export. The concrete artifact the regulated/NIS2 pitch leans on.

Billing / payments

need real account

Stripe/Paddle for subscriptions. Model the plans in ERPNext (business-ops.md); wire a payment provider behind a billing seam. No real charges tonight.

Domain + landing page

need real account

Domain, a static marketing site with the live analyze demo, pricing, trust page.

Legal: ToS / Privacy / DPA

need decision

Especially for EU/regulated buyers; privacy is simplified by the no-outbound-data design (a real selling point — say so in the privacy policy).

Analytics

need decision

Privacy-respecting (e.g. Plausible) for the marketing site only; the appliance phones home to nobody.

Real curated feed content (2 modules)

need decision + ongoing

The actual product. Illustrative samples exist; real curation is the operating discipline.

Client packaging (Docker/compose)

drafted; need Docker env to verify

Multi-stage Dockerfile + docker-compose.yml + docs/deploy.md are written and the runtime model is e2e-verified (binary + assets + volume serve all routes without Docker). What’s pending is running docker build/up in a Docker-capable env (none in this CI) to confirm the base-image layer.

ERPNext for company ops

need decision

Hosting + modeling — see business-ops.md.

Launch gating order: real feed content + verified container + feed hosting (free launch) → billing + landing page + real email/SMTP account (first revenue — the email transport is already built) → hardware signing + Compliance packaging, leaning on the built audit trail (regulated tier). See ttm.md for the critical path and timing.