Ctrl K
ComunidadGuías…

README.md

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

Archivo original ↗Preguntar a KiBot
# DOMINUS — Open-Source Domain Valuation & Domain Portfolio Management Software

> Open-source decision-support engine for domain valuation, buying, reselling, and managing DNS domain portfolios — available as a self-hosted community edition or managed cloud service.

[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](package.json)
[![TypeScript](https://img.shields.io/badge/typescript-6.x-3178C6)](tsconfig.json)
[![Version](https://img.shields.io/badge/version-1.5.3-blue)](package.json)

<!-- The gate is the Woodpecker pipeline (.woodpecker/ci.yml), run locally with `ci-local` (needs Docker) or on a Woodpecker server. GitHub Actions is a billing-blocked mirror, so its badges are not shown. -->

DOMINUS is an **open-source domain investment tool** that helps you make better domain purchase, portfolio, and pricing decisions than the market average. It combines **domain valuation** (heuristic appraisal of market value, buy ceiling, and list price), **expired domain analysis** (age, backlinks, Wayback history), and **domain portfolio management** (renewal clock, keep/drop/reprice verdicts) with a mandatory **trademark check** before any buy recommendation. It is **free to use**, **free to fork**, **zero-cost on APIs**, and designed to run at **€0 infrastructure cost** in its community edition.

**DOMINUS Community** (AGPL v3) — self-hosted, all features, unlimited use, forever free.

**DOMINUS Cloud** — managed hosting with multi-tenant support, PostgreSQL, automated backups with point-in-time recovery, and priority support. Billing, usage metering, and the admin panel ship ahead of the managed hosting launch (v1.0.0).

---

## Product Overview

```mermaid
flowchart LR
    subgraph Pipeline[5-Stage Pipeline]
        A[Candidates] --> B[DNS Pre-filter]
        B --> C[RDAP Confirmation]
        C --> D[Scoring Engine]
        D --> E[Trademark Gate]
        E --> F[Buy / Pass]
    end

    subgraph Portfolio[Portfolio Tracker]
        G[Domain List] --> H[Renewal Clock]
        H --> I[Keep / Drop / Reprice]
    end

    subgraph Cloud[DOMINUS Cloud]
        J[Multi-Tenant] --> K[Auth / Team]
        K --> L[Managed PostgreSQL]
        L --> M[Backups / Monitoring]
    end

    Pipeline --> Portfolio
    Pipeline --> Cloud
    Portfolio --> Cloud
```

### Screenshots

|                                         |                                           |
| --------------------------------------- | ----------------------------------------- |
| ![Dashboard](docs/assets/dashboard.png) | ![Candidates](docs/assets/candidates.png) |
| ![Portfolio](docs/assets/portfolio.png) |                                           |

## Why Open-Source?

Every aspect of DOMINUS is transparent, forkable, and customizable:

- **No vendor lock-in**: you own your data (portable database), your configuration (`.env`), and your fork. Migrate from DOMINUS Cloud to self-hosted with a single database dump.
- **No black-box algorithms**: the scoring engine is heuristic — every weight, threshold, and signal is visible and tunable.
- **No paid APIs required**: all data sources are free (public RDAP, USPTO, EUIPO) or file-based (keyword CSVs, comparable sales). The tool itself never requires a paid subscription.
- **No surprises**: fork the repo, change anything, deploy anywhere — from a Raspberry Pi to a dedicated cloud node.

## Pipeline Architecture

```
Candidates → DNS pre-filter → RDAP confirmation → Scoring → Trademark gate → Buy/Pass
```

Five sequential stages, each feeding the next:

1. **Candidate generation** — keyword combos, brandable names, closeout CSV imports
2. **DNS pre-filter** — fast bulk check via local Unbound recursive resolver (DNSSEC-validated; Node.js DNS fallback for non-Available verdicts only)
3. **RDAP confirmation** — precise availability + premium detection via public RDAP
4. **Scoring** — heuristic engine using intrinsic/commercial/market/expiry signals
5. **Trademark gate** — mandatory USPTO + EUIPO check (non-negotiable)

Plus a **portfolio tracker** with renewal clock and monthly keep/drop/reprice verdicts.

Pipeline runs are **async by default** — enqueued to a job queue and executed by a background worker. Use `--sync` for immediate execution.

### Post-Acquisition Automation (ADR-0083)

Everything after a domain is acquired can run without manual work. The
post-acquisition pipeline executes ordered steps — for-sale page, indexing,
DNS delegation, ads monetization, marketplace listing — journaled per domain
and audited. It ships **dark**: `AUTOMATION_ENABLED=false` and
`AUTOMATION_DRY_RUN=true` by default, so nothing external happens until the
operator enables it deliberately. Steps that need an external account (parking
providers, marketplace APIs) are added behind their interface and report
`skipped` until configured — the pipeline never claims what it cannot do.

```bash
dominus automate settings                 # kill switch + dry-run state
dominus automate run vintagecoffee.com    # run/resume the pipeline for a domain
dominus automate audit                    # what the system did, autonomously
```

See the [automation runbook](docs/guides/automation-runbook.md).

## Quick Start

Install the CLI in one command, no clone required:

```bash
# Linux / macOS
curl -fsSL https://github.com/AlessioBrillo/dominus/releases/latest/download/install.sh | sh

# Windows (PowerShell)
iwr -useb https://github.com/AlessioBrillo/dominus/releases/latest/download/install.ps1 | iex

dominus score vintagecoffee.com
```

The installers download the tarball attached to the latest GitHub Release,
verify its sha256 checksum, and install `dominus-oss` into a user-owned
prefix (`~/.local` on Linux/macOS, `%USERPROFILE%\.local` on Windows) — no
sudo or admin required. On Linux/macOS the command lands in `~/.local/bin`;
on Windows it lands in `%USERPROFILE%\.local`. Add that directory to your
`PATH` if `dominus` is not found after installation. Both installers are
exercised against a real tarball in CI, on both platforms.

The installers use the release alias `dominus-oss.tgz`, which always
resolves to the latest release. If you prefer to download the tarball
yourself:

```bash
# No registry, no clone: the verified tarball and its checksum
curl -LO https://github.com/AlessioBrillo/dominus/releases/latest/download/dominus-oss.tgz
curl -LO https://github.com/AlessioBrillo/dominus/releases/latest/download/dominus-oss.tgz.sha256
sha256sum -c dominus-oss.tgz.sha256
npm install -g ./dominus-oss.tgz
dominus score vintagecoffee.com
```

Or run from source:

```bash
# Clone anywhere, no registration required
git clone https://github.com/AlessioBrillo/dominus.git
cd dominus
npm install
npm run build

# Score a single domain with the bundled sample data. Works with zero
# infrastructure and prints the full decision (ADR-0002).
KEYWORD_DATA_PATH=examples/keywords-sample.json \
COMPS_DATA_PATH=examples/comps-sample.csv \
node dist/cli.js score vintagecoffee.com
```

On Windows (PowerShell) the same thing:

```powershell
git clone https://github.com/AlessioBrillo/dominus.git
cd dominus
npm install
npm run build

$env:KEYWORD_DATA_PATH = "examples/keywords-sample.json"
$env:COMPS_DATA_PATH  = "examples/comps-sample.csv"
node dist/cli.js score vintagecoffee.com
```

```
Score: vintagecoffee.com
  Expected value:    €246.13
  Suggested buy max: €123.06
  List price:        €615.31
  Confidence:        51.8%
  Recommended:       YES (TM clear)

  Trademark gate:
    Verdict:   clear
    Sources:   USPTO
```

That is the whole decision: a conservative expected value, a purchase
ceiling derived from it, a list price, and how much evidence supports it.

The command answers in about two seconds, writes nothing to your disk and
prints the decision on stdout — the diagnostics go to stderr, so the output
can be piped (`dominus score example.com --json` prints the same decision
as an object). The trademark verdict is the live one: a register that does
not answer leaves the domain **unverified**, and an unverified domain is
never recommended (ADR-0012). That is the conservative behaviour, not a
defect: a "yes" on a domain nobody checked is how capital is lost.

### Running the full pipeline

The five-stage pipeline also needs a validating DNS resolver before it can
report a domain as **available**. Without one the DNS stage degrades, the
run is flagged `degraded`, and the CLI exits non-zero on purpose — a
degraded run is a partial answer, and fail-closed is the right signal for
a tool that gates real purchases (ADR-0002).

The easiest way to get a validating resolver is the Docker Compose stack
below, which runs Unbound as a sidecar. With it in place, the sample
closeout run becomes:

```bash
# --sync waits for the run instead of printing a job id
KEYWORD_DATA_PATH=examples/keywords-sample.json \
COMPS_DATA_PATH=examples/comps-sample.csv \
node dist/cli.js run --sync --closeout-csv examples/closeout-sample.csv
```

Or with Docker Compose (recommended — includes the validating Unbound resolver
that "available" verdicts depend on):

```bash
export API_KEYS="admin=$(openssl rand -hex 32)"   # the API refuses to start exposed without auth
echo "$API_KEYS"                                  # keep this: the part after "admin=" is your login key
mkdir -p data  # the container runs as non-root `dominus`: a daemon-created
               # ./data would be root-owned and SQLite cannot open it there
docker compose -f docker-compose.yml -f docker-compose.unbound.yml up -d
```

On Windows (PowerShell):

```powershell
$key = "admin=" + (openssl rand -hex 32)   # or: -join ((1..64) | % { Get-Random -Maximum 16 | % { $_.ToString('x') } })
$env:API_KEYS = $key
$key                                          # keep this: the part after "admin=" is your login key
New-Item -ItemType Directory -Force -Path data  # the container runs as non-root `dominus`
docker compose -f docker-compose.yml -f docker-compose.unbound.yml up -d
```

Then open <http://localhost:3000> and sign in with the key.

If the resolver subnet collides with a network already on your Docker host,
`up -d` aborts with `Pool overlaps with other one on this address space`.
Move it to a free range and retry:

```bash
DOMINUS_UNBOUND_SUBNET=10.99.0.0/24 \
  docker compose -f docker-compose.yml -f docker-compose.unbound.yml up -d
```

A bare `docker run` also works, but without an Unbound resolver the first start
waits ~30 s for it and DNS runs in degraded mode (it never reports a domain as
available):

```bash
docker build -t dominus .
API_KEYS="admin=$(openssl rand -hex 32)" \
  docker run -d -p 3000:3000 -e API_KEYS -v ./data:/app/data dominus
```

### One-command self-hosted start

If you have cloned the repository, `npm run selfhost:up` brings the full
community stack (api, worker, scheduler and the Unbound validating resolver)
from zero to healthy in a single command: it generates an API key, creates
`./data`, starts Compose, waits for `/api/v1/health` and prints the URL and
the admin key. Nothing is written to disk except `./data`.

```bash
npm run selfhost:up
# Open http://127.0.0.1:3000 and sign in with the admin key printed above.
```

## Current Stack

| Layer              | Technology                                      | Why                                                        |
| ------------------ | ----------------------------------------------- | ---------------------------------------------------------- |
| **Backend**        | Node.js 22+, Express 5                          | Zero-cost, universally forkable, massive ecosystem         |
| **Database**       | SQLite (community) / PostgreSQL (cloud)         | Abstraction layer supports both — choose your deployment   |
| **CLI**            | Commander (23 commands)                         | Full functionality without a browser                       |
| **API**            | Express REST (34 route modules)                 | Dashboard-ready, swappable frontend                        |
| **Frontend**       | React 19 + Vite 8 + Tailwind 4                  | Professional SaaS dashboard with Recharts + TanStack Table |
| **Trademark**      | USPTO public API (no key) + EUIPO OAuth2 (free) | Zero-cost compliance                                       |
| **Infrastructure** | Docker, Docker Compose, GitHub Actions          | Deploy anywhere, CI built-in                               |

## Editions

| Feature               | DOMINUS Community                     | DOMINUS Cloud                     |
| --------------------- | ------------------------------------- | --------------------------------- |
| **License**           | AGPL v3 — free forever                | AGPL v3 + managed hosting         |
| **Scoring engine**    | ✓ Full                                | ✓ Full                            |
| **5-stage pipeline**  | ✓ Full                                | ✓ Full                            |
| **Trademark gate**    | ✓ Full                                | ✓ Full                            |
| **Portfolio tracker** | ✓ Full                                | ✓ Full                            |
| **CLI (23 commands)** | ✓ Full                                | ✓ Full                            |
| **REST API**          | ✓ Full                                | ✓ Full                            |
| **Database**          | SQLite (single-file)                  | PostgreSQL (managed)              |
| **Auth**              | Static API key (`.env`)               | SSO (OIDC), team seats + invites  |
| **Multi-tenancy**     | —                                     | ✓ Managed                         |
| **Backups**           | Manual (`dominus maintenance backup`) | Automated, point-in-time recovery |
| **Support**           | GitHub Issues                         | Email/Slack — Enterprise: 4 business hours, see [SLA](docs/operations/sla.md) |
| **Cost**              | €0                                    | Free tier + paid plans            |

## What It Is Not

DOMINUS is decision support, not a guarantee. Before you install:

- **Not financial advice.** Scores, buy ceilings and list prices are heuristic
  estimates, not appraisals. Every weight and threshold is visible and tunable;
  you are responsible for your own purchase decisions.
- **Not a guarantee of a sale.** A high score means the domain looks attractive
  against the configured signals, not that it will sell.
- **Not a legal opinion.** The trademark gate checks public USPTO/EUIPO sources.
  A "clear" verdict is not conclusive, and a match is not legal advice. When
  the sources cannot answer, the domain is reported as **unverified** and is
  never recommended — that is fail-closed behaviour, not a defect.
- **Not a service with an SLA.** The community edition is self-hosted: you own
  the data, the backups and the uptime. There is no response-time commitment.
- **Not DOMINUS Cloud.** Managed hosting, multi-tenancy, automated PITR
  backups and paid tiers are a separate offering and are not part of this
  release.

## Fork & Customize

DOMINUS is designed from the ground up to be forked and personalized. Here's what you can change without touching core code:

### Scoring Engine

Every tunable parameter is exposed via environment variables:

- **Signal strengths**: weights for intrinsic, commercial, market, expiry signals (`SCORING_WEIGHTS_OVERRIDE`)
- **Signal calibrations**: ideal length, volume caps, floor values (see `src/config.ts`)
- **TLD bonuses**: override `.com=1.0, .io=0.85` via JSON file (`TLD_BONUSES_PATH`)
- **Budget caps**: `BUY_MAX_ABSOLUTE_CAP` (0 = uncapped, evidence-anchored value, ADR-0055)
- **Drop logic**: `DROP_SCORE_THRESHOLD`, `DROP_RENEWAL_HORIZON_DAYS`

### Providers

Every external dependency is behind a TypeScript interface. Swap any provider in **one file** (`src/app/composition-root.ts`):

| Interface           | Default              | Swap to                            |
| ------------------- | -------------------- | ---------------------------------- |
| `DnsProvider`       | Node DNS (std lib)   | Any DNS API                        |
| `RdapProvider`      | rdap.org (free)      | Custom RDAP bootstrap              |
| `TrademarkProvider` | USPTO + EUIPO (free) | Commercial TM API                  |
| `KeywordProvider`   | Local JSON file      | Google Ads API, Ahrefs             |
| `CompsProvider`     | Local CSV file       | NameBio API, Estibot               |
| `WhoisProvider`     | Port-43 (free)       | WhoisXML API                       |
| `RegistrarProvider` | Manual (no-op)       | Namecheap, GoDaddy, Cloudflare API |

See [Customization Guide](docs/customization/README.md) for step-by-step examples.

## Deployment Options

DOMINUS scales from a personal CLI tool to a containerized service managing thousands of domains:

| Scenario                    | Stack                            | Command                                                                 |
| --------------------------- | -------------------------------- | ----------------------------------------------------------------------- |
| **Personal** (1-50 domains) | CLI only                         | `curl -fsSL https://github.com/AlessioBrillo/dominus/releases/latest/download/install.sh | sh && dominus run --sync --closeout-csv ./candidates.csv`      |
| **Growing** (50-500)        | Docker (SQLite) + Unbound        | `docker compose -f docker-compose.yml -f docker-compose.unbound.yml up -d` |
| **Large** (500+)            | Docker + PostgreSQL + Unbound    | `docker compose -f docker-compose.yml -f docker-compose.unbound.yml -f docker-compose.prod.yml up -d` |
| **Enterprise** (5000+)      | Terraform (Hetzner) + PostgreSQL | see `deploy/terraform/`                                                 |
| **Managed**                 | DOMINUS Cloud                    | Managed PostgreSQL, automated PITR backups, team seats — availability on request |

See [Deployment Guide](docs/deployment/README.md).

## Configuration

All configuration is via environment variables. Copy `.env.example` to `.env` and customize:

```bash
cp .env.example .env
# Edit .env with your preferences
```

Key variables:

| Variable                   | Default             | Purpose                                                                     |
| -------------------------- | ------------------- | --------------------------------------------------------------------------- |
| `DATABASE_PATH`            | `./data/dominus.db` | SQLite database location                                                    |
| `KEYWORD_DATA_PATH`        | (optional)          | Google Keyword Planner JSON export                                          |
| `COMPS_DATA_PATH`          | (optional)          | NameBio comparable sales CSV                                                |
| `BUY_MAX_ABSOLUTE_CAP`     | `0`                 | Hard cap on recommended buy price (EUR); `0` = evidence-anchored (ADR-0055) |
| `SCORING_WEIGHTS_OVERRIDE` | (optional)          | Custom scoring weights JSON                                                 |
| `TLD_BONUSES_PATH`         | (optional)          | Custom TLD multiplier bonuses JSON                                          |
| `EUIPO_CLIENT_ID`          | (optional)          | EUIPO trademark search (free registration)                                  |
| `API_KEYS`                 | (optional)          | REST API authentication                                                     |

Post-acquisition automation (ADR-0083) is off by default and dry-run by default:

| Variable                   | Default             | Purpose                                                                     |
| -------------------------- | ------------------- | --------------------------------------------------------------------------- |
| `AUTOMATION_ENABLED`       | `false`             | Kill switch. When false, every automation run is refused and audited        |
| `AUTOMATION_DRY_RUN`       | `true`              | When true, steps that spend money or mutate DNS skip instead of acting      |
| `INDEXNOW_KEY`             | (optional)          | IndexNow key: serves `/<key>.txt` and submits for-sale pages to Bing/Yandex |
| `AUTOMATION_CONTACT_EMAIL` | (optional)          | Contact address published on for-sale pages (offer mailto)                  |
| `AUTOMATION_AUDIT_RETENTION_DAYS` | `90`         | Retention of the automation audit trail (pruned by the data-prune job)      |

See [full reference](docs/customization/configuration.md).

## Commands

```
Usage: dominus <command> [options]

Commands:
  run                 Run the full pipeline
  score               Score a single domain
  portfolio           Manage portfolio (CRUD + rescore)
  outcome             Record outcomes (sold/dropped/expired)
  backtest            Run backtest + suggest weight adjustments
  runs                List/inspect pipeline runs
  candidates          List pipeline candidates
  maintenance         Prune cache, backup, DB maintenance
  providers           Show provider status
  health              System health check
  listing             Manage marketplace listings
  automate            Post-acquisition automation pipeline (status, run, reset, audit)

Commands registered only when their dependency is enabled:
  scheduler           Run scheduled jobs manually   (SCHEDULER_ENABLED=true)
  watchlist           Monitor domains for availability
  buy, registrars     Purchases and registrar config (an active RegistrarProvider)
  report              Generate portfolio reports
  analytics           Prediction accuracy and P&L analytics
  bid                 Manage bids
  funnel              Inspect the acquisition funnel
  keys                Manage scoped API keys       (DB-backed auth)
```

Run `dominus --help` for the commands available in your installation — the
list above is a subset of what the binary registers.

## Documentation

- Guides: [closeouts to a buy decision](docs/guides/closeouts-to-buy-decision.md),
  [portfolio keep/drop](docs/guides/portfolio-keep-drop.md),
  [automation runbook](docs/guides/automation-runbook.md),
  [self-hosting](docs/guides/self-hosting.md),
  [Cloud teams, SSO and operators](docs/guides/cloud-team-sso.md)
- [Architecture Decision Records](docs/adr/README.md) — full architectural rationale
- [Customization Guide](docs/customization/README.md) — how to adapt for your needs
- [Deployment Guide](docs/deployment/README.md) — infrastructure options
- [Contributing Guide](CONTRIBUTING.md) — how to contribute
- [Security Policy](SECURITY.md) — vulnerability reporting
- [Roadmap](ROADMAP.md) — planned features and releases
- [Upgrading to 1.1.0](docs/releases/upgrade-1.1.0.md) — breaking changes and removals
- [Service level agreement](docs/operations/sla.md) — Enterprise support commitments

## Project Status

DOMINUS v1.5.3 — The artifact tells the truth: `dominus doctor` reports its own version,
database state, backup age and disk space on any installation, fresh or existing.
pipeline (`.woodpecker/ci.yml`), run locally with `ci-local` (needs Docker)
or on a Woodpecker server; GitHub Actions is a billing-blocked mirror and
its badges are not shown. The migration gate takes a cross-process lock and
a pre-migration snapshot, `dominus doctor` inspects without mutating, and
`selfhost:up` brings a stack from zero to healthy in one command.
`npm run launch:check` now judges a **community** deployment (the AGPL and
the self-hosted data flow, no operator identity to publish) and a **Cloud**
deployment (identity, Stripe, backups, probe, audit) with the same
implementation, and `--paid` turns the Cloud contracts into hard failures.
The gate writes evidence (`launch-evidence-<version>-<sha>.json` and `.md`)
on pass and on fail, so a release can attach what approved it.
`npm run launch:rehearse` builds the production-parity Cloud stack, runs the
gate against it and tears it down, with no credentials and no spend; the
community edition is the first soft launch, and the Cloud stays behind the
fiscal position, the third-party audit and a real staging deployment
([first-apply.md](docs/deployment/first-apply.md)). `dominus score
example.com` still answers in about two seconds, creates nothing on disk and
prints the decision and nothing else on stdout. All five pipeline stages,
the heuristic scoring engine, the mandatory trademark gate enforced on every
purchase path (API, CLI, auto-approval, bid), real USPTO/EUIPO providers
with caching, the portfolio tracker with renewal clock and keep/drop
verdicts, outcomes, the backtest engine and the React dashboard are
implemented and tested. Post-acquisition automation (ADR-0083) ships dark
by default (`AUTOMATION_ENABLED=false`). The community edition is fully
functional; DOMINUS Cloud adds multi-tenancy, team accounts with email
invitations, SSO and Stripe billing. See [docs/releases/upgrade-1.1.0.md](docs/releases/upgrade-1.1.0.md)
and the [CHANGELOG](CHANGELOG.md) for the release history.

## FAQ

**How does DOMINUS value a domain?**
DOMINUS uses a transparent heuristic appraisal engine with four signal groups: intrinsic quality (length, pronounceability, hyphens/numbers, TLD bonus), commercial demand (keyword search volume × CPC), market comparables (NameBio sales data), and expiry signals for expired/closeout domains (age, backlinks, Wayback snapshots). Every weight is visible and tunable — no black box. The engine is deliberately **more conservative than commercial appraisal tools**.

**Is DOMINUS really free?**
Yes. The community edition is AGPL v3, self-hosted, and runs on free data sources (public RDAP, USPTO, EUIPO). No paid API is required and there is no feature gating — DOMINUS Cloud monetises hosting only.

**What is the trademark gate?**
Before recommending any buy, DOMINUS checks the candidate against USPTO and EUIPO trademark records. Any match blocks the candidate. This check is mandatory and cannot be bypassed — see [ADR-0006](docs/adr/0006-trademark-gate-mandate.md).

**Does DOMINUS support expired domain analysis?**
Yes. Import closeout CSVs of expired domains and DOMINUS carries age, backlinks, and Wayback history into the expiry signal, then runs the same DNS/RDAP availability verification and trademark gate.

**How does DOMINUS check if a domain is available?**
A two-stage gate: a fast DNS pre-filter against a validating recursive
resolver (Unbound with DNSSEC validation, running as a Docker sidecar),
followed by authoritative RDAP confirmation with an opt-in second-opinion
check. Verdicts are fail-closed — without a validating resolver the DNS
stage degrades and never reports a domain as available, and a disagreement
downgrades the verdict to "unknown" rather than trusting a single source.

**How is DOMINUS different from Estibot, GoDaddy Appraisal, or Sedo?**
Those are closed, often sales-leveraged appraisals. DOMINUS is open source (you can audit every weight), conservative by design, and decision-first: the output is a clear _buy/pass_ verdict with a purchase ceiling, not a marketing number. It also manages the portfolio after purchase (renewal clock, keep/drop/reprice) and integrates the trademark gate into the workflow.

**Can I self-host DOMINUS?**
Yes — from a single Raspberry Pi (SQLite) to Docker Compose with PostgreSQL, Redis, Prometheus and Grafana, to a Terraform-provisioned node. See the [Deployment Guide](docs/deployment/README.md).

## License

**AGPL v3 only** — © 2026 AlessioBrillo. DOMINUS Community is free and
open-source software: you may use, study, share, and modify it, and you may
offer modified versions as a network service **provided you publish your
modifications** under the same license (AGPL §13). See [LICENSE](LICENSE).

Commercial licenses are available for organizations that require proprietary
embedding or proprietary SaaS without AGPL obligations. See
[COMMERCIAL_LICENSE.md](COMMERCIAL_LICENSE.md).

Third-party dependencies and bundled data licenses are listed in
[THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). Dependency licenses are
enforced in CI (`license:check`).

### Corresponding Source (GitHub Release installations)

When you install DOMINUS from the GitHub Release tarball
(`dominus-oss.tgz`) you receive `dist/`, which is compiled output — it is
not the Corresponding Source the AGPL requires you be able to obtain and
rebuild.

The complete source for every published version is available, free of
charge, at the exact tag the release was built from:

```bash
git clone https://github.com/AlessioBrillo/dominus.git
git checkout v<version>
npm ci && npm run build
```

Every file the release ships under `files` in `package.json` is generated
by that build, and `npm run check:pack` verifies the artifact is complete.
The build needs no paid credentials: providers that would require an API
key degrade to free or manual sources (ADR-0002, ADR-0004).

This section is a written offer for the Corresponding Source, valid for
three years from the date you received the object code, as AGPL §6(b)
requires.

### Trademark

The name "DOMINUS" identifies this project and is claimed by its author,
AlessioBrillo, as a project mark. The AGPL license grants you the right to
copy, modify, and distribute the code — it does **not** grant you the right
to use the DOMINUS name or logo to promote your fork or a competing
service. Forks and derived services must use a different name and must not
imply affiliation with or endorsement by the DOMINUS project. Proceed with
your own fork and your own brand.