Ctrl K
ComunidadGuías…

ROADMAP.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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/<domain>` (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 `<prefix>/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-<version>-<sha>.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._