# Roadmap DOMINUS v1.0.0 - DOMINUS Cloud MVP (released). v1.1.0 - Release hardening (released). v1.2.0 - Post-acquisition automation (released; the marketplace vendor adapters remain blocked on vendor access). v1.3.0 - Launch readiness: the legal surface, the tax and consent compliance, the data-subject rights, the launch gate and the verified artifact (released). v1.3.2 - The front door: a decision command that answers, a trademark gate that fails closed, and a release state that is real (released). v1.3.3 - The trademark gate answers again on the migrated USPTO endpoint (ADR-0098, released). v1.3.4 - The front door is verified: the installers and the published tarball are exercised on both platforms, and a tag does not publish while the live trademark canary is red (released). v1.4.0 - First Light: mode-aware launch gate with evidence, a launch rehearsal on the production-parity stack, the audit scope and the first-apply runbook; the community edition is the first soft launch (released). v1.5.0 - First Boot: local-first release engine, PostgreSQL migration lock fixes, pre-migration backup, `dominus doctor`, `selfhost:up` (released). v1.5.1 - The Gate Leaves GitHub: the merge gate moves from GitHub Actions (billing-blocked) to Woodpecker (`.woodpecker/ci.yml`, local-first via `ci-local`); ADR-0101 documents the local-first release engine; front-door polish (`--help`/`--version`/`score --help` silent on stderr); release and launch documentation describe the real publishing path (released). Next: execute the first staging apply (v1.6.0), the third-party audit, the fiscal position, and only then the paid Cloud tiers. This roadmap outlines the planned releases and their scope. Timelines are estimates and subject to change. ## v0.4.0 — SaaS Foundation > **Status**: Completed - [x] ADR-0025 through ADR-0028 - [x] AGPL v3 + commercial license, CLA, OpenAPI docs ## v0.5.0 — Production Hardening > **Status**: Completed > **Focus**: Security, code quality, retry consolidation, benchmarks - [x] CSP hardening, AuthProvider DI, rate limiting, retry consolidation - [x] Circuit breaker, DnsProvider interface, benchmark suite - [x] API error handler consistency, architecture diagrams, changelog generation - [x] Codecov integration + coverage badge in README - [x] SEO-ready README with screenshots (generated by `e2e/screenshots.spec.ts`) ## v0.6.0 — Database Abstraction > **Status**: Completed - [x] DatabaseProvider interface, SQLite + PostgreSQL adapters - [x] All repositories refactored, RLS policies, migration path ## v0.7.0 — Authentication & Multi-Tenancy > **Status**: Completed (foundation laid) > **Focus**: User management, tenant isolation, JWT auth - [x] API key management (DB-backed, scrypt hashed) - [x] `tenant_id` context resolution middleware + RLS policies - [x] Community edition retains static `.env` API key (backward compatible) - [x] Auth0 OIDC single sign-on (ADR-0062). Refresh tokens are intentionally not implemented: sessions last 8 hours and end at expiry or logout. ## v0.8.0 — Conversion Features & Onboarding Wizard > **Status**: Completed - [x] Onboarding wizard, portfolio import, savings callout - [x] Shareable score pages, analytics events ## v0.9.0 — Professional Frontend Dashboard > **Status**: Completed - [x] Recharts, TanStack Table, shadcn/ui, auth flow, themes - [x] Loading skeletons, React Query, error boundaries - [x] Accessibility pass (WCAG 2.1 AA): `jsx-a11y` lint plus an axe-core E2E gate on the main flows, in light and dark themes (v1.1.0) - [x] Frontend test coverage ≥50% ## v0.10.0 — Operations & Reliability > **Status**: Completed > **Focus**: Load testing, security audit, CI/CD maturity, bridge repair - [x] Fix: POST /portfolio/verdicts route (frontend 404 bug) - [x] Fix: Cloudflare purchase priceEur: 0 bug - [x] Fix: frontend login validation (API key verified against backend) - [x] Tests: dan-listing-provider (0% → 85%+), auto-listing-service (0% → 90%+) - [x] Tests: listings route (0% → 18 tests covering all CRUD + offers) - [x] Pagination: Dan sync + Cloudflare listDomains - [x] Load testing and performance benchmarking (see `npm run bench`; live-network benches against real resolvers/registries: `DNS_LIVE=1 npm run bench`) - [x] DNS verdict hardening: 2-of-3 consensus on by default with endpoint-level disjointness enforcement (no shared resolver between primary and secondary), parking IP probe under rate limit/deadline/abort - [x] Security: timing-safe API key comparison (`EnvApiKeyProvider`) - [x] Rate limiting: distributed Redis-backed store for the public router - [x] Backend test coverage thresholds raised to 70/65/60 (lines/functions/branches) - [x] CI matrix testing (Node 22 + 24 on ubuntu and windows, native-bindings smoke check) - [x] Compose topology fix: the documented prod command now starts the full stack (worker/scheduler by default; PG/Redis/monitoring via the prod overlay) — guarded by a CI job that asserts the service sets - [x] Observability: Prometheus text-format endpoint (`GET /api/v1/metrics/prometheus`), self-hosted Prometheus + Alertmanager + Grafana in the prod profile, alert rules for API down / provider error rate / stage errors / stuck queue / dead letters - [x] Restore drill script (`scripts/restore-drill.mjs`) — backup, restore, integrity_check and row-count comparison; failure path verified - [x] CI matrix testing (Node 22 + 24 on ubuntu and windows, native-bindings smoke check) - [x] Codecov integration + coverage badge in README - [x] Security audit (dependency scan, CSP review, auth hardening) — `npm audit` reports 0 vulnerabilities in both workspaces; the script runs with `--omit=dev`, and the frontend tree is clean in full - [x] Frontend coverage thresholds raised to ≥70% (enforced in CI via `npm run test:coverage`; vitest thresholds 70/70/70 statements/lines/functions and 60 branches) ## v0.11.0 — Consensus Hardening (released) > **Status**: Completed > **Focus**: Availability-verdict trust, distributed rate limiting, usage enforcement - [x] Usage enforcement at chokepoints (ADR-0038): metered candidate scoring, API calls, portfolio tracking - [x] DNS consensus: majority-vote 2-of-3 gate on every resolution path (ADRs 0039, 0040), tertiary leg (0045), private recursor (0042), budget + DoH keep-alive pooling (0044), live-verified DoH legs (0047, 0048) - [x] RDAP consensus: opt-in 2-of-2 second opinion (0050), WHOIS rescue leg + startup probe (0051), transport parity / undici pool (0049) - [x] Distributed per-tenant fair share on shared Redis budgets (0041, 0052) - [x] Configurable per-IP public rate limits (0043), image supply-chain pinning (0046) ## v0.10.1 — Hardening Polish > **Status**: Completed (scope shipped with the v0.11.0 release) > **Focus**: DNS consensus strictness, metrics access control, release docs - [x] DNS verdict hardening: 2-of-3 consensus is now _strict_ — a failed or unknown secondary resolver downgrades the verdict to Unknown instead of trusting the primary, plus a startup probe that fails fast when the consensus provider is misconfigured - [x] DNS consensus failure policy (ADR-0039): fail-closed with a visible `consensus-unverified` degraded-run flag, majority + floor knobs (`DNS_CONSENSUS_DEGRADED_RATIO`/`_MIN`), and `dominus_dns_consensus_*` Prometheus tallies - [x] Metrics access control: optional `METRICS_TOKEN` bearer auth on the `/api/v1/metrics/*` router (401 when set and not presented; unchanged when unset), with a commented Prometheus scrape authorization block for operators who enable it - [x] Documentation: SQLite multi-process concurrency limits in the deployment guide, `.gitignore` covers benchmark output - [x] SEO-ready README (FAQ, keyword-rich intro, semantic headings; screenshot/GIF demo deferred to v1.0.0 launch assets) ## v1.0.0 — DOMINUS Cloud MVP & Programmatic SEO > **Status**: Released > **Focus**: Managed hosting, billing, paid tiers, SEO - [x] DNS consensus strictness and per-endpoint circuit breakers (ADR-0059): `DNS_CONSENSUS_REQUIRED_AVAILABLE` gate (default 1 — one independent confirmation per ADR-0002; knob up to 2 for triple agreement), breaker registry on every resolver leg with `dominus_dns_breaker_*` metrics, bundled parking-IP reference list, watchlist single-provider labelling - [x] DOMINUS Cloud infrastructure (VPS + PostgreSQL + reverse proxy) — Hetzner IaC in `deploy/terraform/` (app node + PITR DB node + Caddy) - [x] Free tier: rate-limited pipeline runs, single user - [x] Pro tier (€29/mo): 500 candidates scored/month, 3 team seats, email support (support channel is ops, deferred to v1.1.0) - [x] Team tier (€79/mo): 2,500 candidates scored/month, 10 team seats, Slack support (support channel is ops, deferred to v1.1.0) - [x] Stripe billing integration (subscriptions + customer portal) — incl. Team checkout and status-aware enforcement (ADR-0053) - [x] Usage metering (pipeline runs, API calls per tenant) - [x] Admin panel (tenant lifecycle + usage metrics — ADR-0057: overview, per-tenant daily usage drill-down, suspend/unsuspend, plan override) - [x] Automated daily backups with point-in-time recovery (ADR-0054: `deploy/postgres/base-backup.sh` + restore drill script) - [x] Monitoring and alerting (uptime, error rate, latency — Prometheus/Alertmanager/Grafana stack in the prod compose profile) - [x] Migration guide: from community edition to DOMINUS Cloud (`docs/migration/community-to-cloud.md`) - [x] `AnonScoringService` — scoring engine in no-persist mode for public endpoints - [x] `GET /public/domain/:name` — public domain valuation page (crawlable, cached) - [x] `GET /sitemap.xml` — dynamic sitemap with public pages - [x] `GET /public/compare/:slug` — editorial comparison pages - [x] JSON-LD structured data for rich snippets - [x] SSR layer for public pages (server-rendered HTML views — see [ADR-0030](docs/adr/0030-public-namespace-architecture.md)) - [x] Off-host backups made mandatory by default with a dedicated backup volume (ADR-0054: `#341`) and the base-backup manifest recorded in the `pitr_health` table (`#342`) - [x] RDAP origin-overlap guard fail-closed: a resolver failure on the authoritative-origin lookup skips the second leg and downgrades the verdict as unverifiable (ADR-0060, `#344`) - [x] CI reliability: dead-letter tests pinned to a past `scheduled_at`, fixing the flaky `getDeadLetter respects limit` (`#343`) ## v1.1.0 — Release Engineering Safety > **Status**: Released > **Focus**: Release engineering safety, tenant isolation and PostgreSQL > parity, accessibility, and removing features that never worked - [x] Schema migration gate: fail-closed manifest prefix check at boot and deploy, destructive-DDL scanner in CI, RTO/RPO documentation (#349) - [x] Migrate-before-roll: explicit migration step with a dedicated timeout before the roll; the old image keeps serving while migrations apply (ADR-0061) - [x] DNS consensus hardening: native resolver leg pinned to the private recursor, rigorous DNSSEC (SERVFAIL-on-bogus) (#350) - [x] DNS fail-closed parity: escaped resolver errors are never manufactured into Available verdicts (ADR-0002 conservatism) - [x] Billing surface E2E coverage (community edition, fail-closed checkout) - [x] Enterprise SSO via Auth0 OIDC (ADR-0062, interactive PKCE flow + session cookies) - [x] Enterprise tier: per-tenant Stripe prices and SSO shipped; SLA published in `docs/operations/sla.md`; dedicated infrastructure is provided on contract (Terraform modules in `deploy/terraform/`), not as a self-service product - [x] Platform operator role (`OPERATOR_SUBJECTS`): tenant admins can no longer reach the cross-tenant admin surface (ADR-0081) - [x] Tenant isolation: domain uniqueness per tenant, tenant-scoped run history, no tenant leak on pooled PostgreSQL connections - [x] Team invitations by email (single-use links, optional SMTP) and SSO sign-in resolved from team seats (ADR-0081) - [x] PostgreSQL parity: portable SQL (checked in CI), repository parity tests, and a CI job that runs the suite against a real PostgreSQL - [x] Release pipeline: distinct `vX.Y.Z` / `-worker` / `-scheduler` image tags, working container image, OpenAPI contract tested against the routers - [x] Removed features that were declared but never functional: per-query DNSSEC, DoH fallbacks, Dan/Afternic/Sedo adapters, Kubernetes manifests (ADR-0082) - [x] First-party security review of the multi-tenant surface (v1.1.0) - [ ] Third-party security audit (when budget allows) - [ ] Public launch: Product Hunt, Hacker News, domain investor communities - [x] Workflow guides in `docs/guides/` (closeouts to a buy decision, portfolio keep/drop, Cloud team setup with SSO, self-hosting) - [ ] Customer case studies (need real customers) - [ ] Community Discord server ## v1.2.0 — Post-Acquisition Automation (ADR-0083) > **Status**: Released (the M4 vendor adapters stay blocked on vendor access) > **Focus**: automated lifecycle after the buy decision — site, indexing, > DNS delegation, parking/monetization, marketplace listing - [x] Post-acquisition pipeline: journaled steps (`post_acquisition_steps`), audit trail (`automation_audit`), kill switch `AUTOMATION_ENABLED` (default off) and dry-run `AUTOMATION_DRY_RUN` (default on) - [x] `POST_ACQUISITION` job type on the existing queue; purchase and won-auction paths trigger the pipeline instead of the old fire-and-forget auto-list - [x] `listing` step (delegates to the existing AutoListingService) - [x] Bug fix: `AUTO_LIST` / `POST_ACQUISITION` job handlers are now registered by the worker (previously enqueued jobs dead-lettered) - [x] CLI `dominus automate settings|status|run|reset|audit`, API `/api/v1/automation/*`, OpenAPI coverage, operator runbook - [x] **M2** — `site` + `indexing` steps: landing page generated from scoring data and published at `/public/for-sale/` (Schema.org Offer), sitemap inclusion, IndexNow submission (`INDEXNOW_KEY`), contact via `AUTOMATION_CONTACT_EMAIL` - [x] **Phase 0** — tenant opt-in: `tenant_automation_settings` (per-tenant kill switch/dry-run, conservative combination with the env brake), `PUT /automation/settings`, Automation dashboard page (settings, step journal, audit trail), `dominus automate settings --enabled/--dry-run` - [x] **M3** — `dns` + `parking` steps: DnsWriteProvider (Cloudflare-first, manual fallback) behind a fail-closed write gate (ADR-0083 amendment), MonetizationProvider with a CSV revenue reader (zero paid API dependencies; provider API adapters land with verified access, ADR-0082), revenue ingestion idempotent per (domain, date, source) - [x] **M4 (partial)** — marketplace automation without unverified vendor APIs: tenant listing policy (`tenant_listing_settings`): fixed base price for automatic listings, offer auto-decline floor and counter rule (both conservative by default), `GET/PUT /api/v1/listings/settings`, listing policy card in the dashboard - [ ] **M4 (vendor adapters)** — Dan.com + Afternic ListingProvider adapters and offer sync: blocked on verified API access (ADR-0082); they return once the vendors grant and verify the credentials - [x] **M5** — sustainability: scheduled revenue ingestion (`REVENUE_SYNC` job + `revenue-sync` scheduler job, read-only, idempotent), carry-cost verdict (`sustainable` / `marginal` / `loss` / `insufficient_data`, 30-day minimum before judging) exposed at `GET /api/v1/sustainability` and in the Portfolio dashboard, and fed into the drop engine as a Reprice signal (never an auto-drop) ## v1.3.0 — Launch readiness (ADR-0090, ADR-0091, ADR-0092, ADR-0093, ADR-0094) > **Status**: Released — the code is done; what remains is the operator's > work (identity, fiscal position, infrastructure, audit) > **Focus**: the public launch of DOMINUS Cloud — the legal surface, the > tax and consumer-law compliance, the data-subject rights, and a launch > gate that can be executed - [x] Legal surface rebuilt for the right jurisdiction (art. 7 D.Lgs. 70/2003, not the German Impressum): legal notice, terms of service and privacy notice as server-owned structured data, published unauthenticated, linked from the footer of every public page - [x] Identity as configuration (`LEGAL_*`), never as a placeholder: the launch gate refuses a deployment whose identity is missing - [x] Community edition publishes the documents that apply to it (AGPL, self-hosted data flow) and never the operator identity - [x] Stripe Tax completed: billing address required, VAT ID collected for the EU reverse charge, customer address written back on returning customers - [x] EU consumer law: the art. 59(1)(o) consent and its acknowledgement are collected at checkout, in one constant, asserted by the tests - [x] Data-subject rights: export (art. 15) and erasure (art. 17) from the API and the CLI, over one registry of tenant-scoped tables that cannot drift from the schema - [x] Data processing agreement (art. 28) template, sub-processor list and retention table published - [x] `npm run launch:check`: the launch state is executable, not a document — exit 0 or exit 1 - [x] The green trunk: the E2E suite is part of the local gate, the secret-scanning false positives are gone, the master is green - [x] The published artifact is verified, not assumed (ADR-0091): the local gate installs and runs the tarball before a tag, the release workflow installs and runs the published package after the publish, and the release rehearsal works from a branch again - [x] The granted plan is derived from the Stripe price id, never from the session metadata (ADR-0093); an unknown price id grants nothing - [x] The launch posture is measured, not promised (ADR-0094): one replica stated in the SLA, an external availability probe outside the app node, a real PITR rehearsal, and fail-closed SSH ingress - [x] The community first run does not wait thirty seconds for a resolver that is usually not there (ADR-0092) - [ ] Operator identity (name, address, P.IVA, REA, PEC, contacts) - [ ] Fiscal position and the accountant: OSS registration, the invoice series, the reverse-charge wording, the review of the legal texts - [ ] The three Stripe verification scenarios, recorded - [ ] The infrastructure, provisioned for real: `terraform apply`, DNS, TLS, a real Alertmanager webhook, an external probe, a restore drill against the real backup target - [ ] The third-party security audit, before the paid tiers - [ ] The npm trusted publisher, so `dominus-oss` is installable - [ ] Public launch: Product Hunt, Hacker News, domain investor communities ## v1.3.2 — The front door (ADR-0097) > **Status**: Released > **Focus**: the first command a stranger runs, and the truth of what the > repository announces about itself - [x] The decision profile: `dominus score` builds the scoring engine and the trademark gate and nothing else — no database, no job worker, no resolver probe (12.4 s → ~2.5 s, and nothing written to the disk) - [x] The catalog profile: `--help` and `--version` are answered from the command line alone (10.4 s → ~1.4 s), with a test that keeps the two command lines identical - [x] The diagnostics moved to stderr: stdout carries the decision and nothing else, so the output can be piped - [x] `dominus score --json`: the same decision, as an object - [x] The trademark providers fail closed: a source that cannot answer is an error, not "no matches". A domain whose trademark was not checked is reported as unverified, and an unverified domain is never recommended - [x] The quickstart gate (`npm run check:quickstart`): the advertised command is executed and its contract is asserted, and the output documented in the README is compared with the output produced - [x] The release doctor (`npm run release:doctor`): the version `package.json` announces must have a tag, a clean tree and — with `--remote` — a package and an image - [x] The verified tarball and its checksum are attached to the GitHub Release: the community edition is installable without the npm registry - [x] **The USPTO endpoint migration** — closed in v1.3.3 (ADR-0098): the provider reads the `prod-stage-v1-0-0` endpoint and the gate answers `clear`/`blocked` again ## v1.3.3 — The trademark gate answers again (ADR-0098) > **Status**: Released > **Focus**: the one non-negotiable gate, after the upstream endpoint moved - [x] USPTO provider migrated to the `prod-stage-v1-0-0` search endpoint - [x] The gate reports `clear` or `blocked` instead of `unverified` on a live query, and still fails closed on an unanswerable source ## v1.3.4 — The front door is verified > **Status**: Released > **Focus**: the release is verified against what a stranger downloads and > runs, not against the repository's opinion of itself - [x] The installers install a working command: `npm install -g` puts the binary in `/bin` on Linux/macOS and in the prefix on Windows, which is where the scripts say it is - [x] `npm run test:installers` runs the real installer against a local HTTP server that serves the real tarball, on Linux and Windows, and asserts a working `dominus score` and a refused corrupted checksum - [x] `check:published-install` is fixed and wired: it starts the trademark fixture before reading its port, measures the time budget, resolves a release tag URL to the alias tarball, and asserts a `clear` verdict - [x] The release workflow verifies the GitHub Release channel after the publish, even when the npm publish fails, and asserts the alias tarball, its checksum and both installers are attached - [x] The live trademark canary blocks the release: a tag does not publish while `npm run check:trademarks` is red (ADR-0098's claim, made true), and a daily schedule opens an issue when the endpoint drifts - [x] The npm channel is documented for what it is: best-effort until the trusted publisher is configured; the GitHub Release is primary and verified end-to-end ## v1.4.0 — First Light (ADR-0100) > **Status**: Released > **Focus**: the launch bar is executable before the infrastructure exists, > and the community edition ships first - [x] `launch:check` has `--community` and `--cloud` profiles, auto-detects the mode with the server's own rule, and adds `--paid` for the Cloud contracts - [x] `--evidence` writes `launch-evidence--.json` and `.md` on pass and on fail - [x] the gate checks the canonical origin (configured and rendered), TLS, HSTS/CSP, HTTP→HTTPS, HTML/JSON parity, robots → sitemap, public input validation, data-rights endpoints and the live trademark canary - [x] `npm run launch:rehearse` builds the production-parity Cloud stack, runs the gate against it, writes the evidence and tears it down; PITR is opt-in and a missing prerequisite is a SKIP, never a pass - [x] the audit scope is a statement of work, and the evidence index maps every claim to the command that produces it - [x] the first-apply runbook goes from an empty Hetzner project to a gate-green staging deployment - [x] the community soft-launch runbook, with the announcement and the support posture ## Post-1.0 - **Internationalisation** (after v1.4.0) — the legal documents and the interface as a translatable catalogue, with machine-assisted translation that opens a pull request and a check that no user-facing string can bypass the catalogue. Runtime translation is excluded: it would send user data to a third party, and it is neither indexable nor cacheable. - **Real-time collaboration** — WebSocket-based shared pipeline views - **Advanced analytics** — Portfolio diversification heatmaps, trend analysis - **Name generator** — AI-assisted brandable domain generation - **Marketplace integrations** — Afternic, Sedo, Dan.com, GoDaddy Auctions. Adapters shipped in 1.0.x were removed in 1.1.0 because they were never verified against the vendors' APIs (ADR-0082); they return once API access exists - **Tenant switcher** — follow-up to ADR-0081 - **Row-level security on control-plane tables** — needs a dedicated bypass design - **Mobile app** — Native notifications for renewal alerts and bid updates - **Multi-replica rate limiting** — the protected router counts per replica; the shared store arrives with the multi-replica topology --- > _This roadmap is a living document. Priorities may shift based on user > feedback and business needs. See the [ADR series](docs/adr/README.md) for > the rationale behind major decisions._