Operating Modes

depends.cc runs in self-hosted (default) or hosted mode, auto-detected at startup via process.env.LEGENDUM_API_KEY. Self-hosted mode (no key set) bypasses auth, billing, and signup—ideal for local development, private networks, or trusted infrastructure. Hosted mode (key set) enables multi-tenant bearer-token auth, Legendum billing, and SMTP email delivery.

The core model (nodes, edges, effective states, TTL, notifications) is identical across modes. See project-invariants.md for key behaviors like lazy TTL evaluation and no server-side polling.

Mode Detection

// src/server/middleware.ts (excerpt)
export function isByLegendum(): boolean {
  return !!process.env.LEGENDUM_API_KEY;
}
export function isSelfHosted(): boolean {
  return !isByLegendum();
}

Restart required to switch modes.

Self-Hosted Mode

No LEGENDUM_API_KEY. Requests map to well-known LOCAL_TOKEN = "dep_local" (token ID 0); namespaces auto-create on first access. Authorization header optional/ignored. Rate limiting skips localhost (127.0.0.1, ::1): 120 requests/minute per IP otherwise.

Quickstart (Local Development)

Install CLI (includes server):

curl -fsSL https://depends.cc/install.sh | sh
depends serve  # http://localhost:3000 (data/depends.db created)

Or directly:

bun install
bun run dev    # Watch mode
bun run start  # Production; override PORT=8080

CLI auto-detects local mode (no DEPENDS_TOKEN):

depends init    # Scaffold depends.yml
depends push    # Sync graph
depends status  # View states
depends set myproject/api-server red

Explicit: DEPENDS_API_URL=http://localhost:3000/v1 depends status.

Events auto-purge hourly (older than 30 days; see data-purging.md). Admin: depends admin tokens.

Database and Logs

tail -f log/$(date -u +%F).log
grep '"kind":"webhook_failed"' log/$(date -u +%F).log

Hosted Mode (Production)

Set LEGENDUM_API_KEY (Legendum service key). Enforces Authorization: Bearer dep_... (per-account, namespace-scoped via ownership). Signup required.

Deployment Steps

  1. Clone: git clone /opt/depends && cd /opt/depends.
  2. bun install.
  3. Set env vars (minimum: LEGENDUM_API_KEY).
  4. Start: bun run src/server.ts.
  5. Reverse proxy for HTTPS.

Reverse Proxies

Nginx:

server {
  listen 443 ssl;
  server_name depends.cc;
  ssl_certificate /etc/letsencrypt/live/depends.cc/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/depends.cc/privkey.pem;
  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Caddy:

depends.cc {
  reverse_proxy localhost:3000
}

Systemd

[Unit]
Description=depends.cc
After=network.target
[Service]
ExecStart=/usr/bin/bun run /opt/depends/src/server.ts
WorkingDirectory=/opt/depends
EnvironmentFile=/etc/depends/env
Restart=always
User=depends
[Install]
WantedBy=multi-user.target

Signup and Tokens

depends signup you@example.com lak_...  # lak_... from legendum.co.uk/account

Token emailed. Tokens hash-stored (SHA-256), own namespaces:

-- src/db.ts (excerpt)
CREATE TABLE tokens (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  token_hash TEXT NOT NULL UNIQUE,
  email TEXT,
  legendum_token TEXT,
  ...
);
CREATE TABLE namespaces (
  ns_id INTEGER PRIMARY KEY AUTOINCREMENT,
  id TEXT NOT NULL,
  token_id INTEGER NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,
  UNIQUE(token_id, id)
);

CLI config (~/.config/depends/config.yml or DEPENDS_TOKEN):

token: dep_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
default_namespace: myproject
api_url: https://depends.cc/v1

See cli.md.

Billing

Legendum credits per action (self-hosted skips):

ActionCost
Node create1
State write0.1
Webhook/Email2

GET /usage/{ns} stats (api-reference.md). 402 on insufficient funds.

Emails via SMTP (notifications.md).

Key Differences

AspectSelf-HostedHosted
LEGENDUM_API_KEYUnsetSet
Authdep_local (auto)Bearer dep_... (signup)
NamespacesAuto-createToken-owned (POST /namespaces)
BillingNoneLegendum
EmailsSkippedSMTP
Rate LimitingSkip localhostAll IPs

Environment Variables

Server:

VariableDefaultDescription
PORT3000Listen port
LEGENDUM_API_KEYUnsetEnables hosted mode
BASE_URLhttps://depends.ccAck URLs (notifications.md)
SMTP_HOSTUnsetSMTP hostname
SMTP_PORT465SMTP port (TLS)
SMTP_USERUnsetSMTP user
SMTP_PASSUnsetSMTP password
SMTP_FROMnotifications@depends.ccFrom address

CLI (ignored by server):

VariableDescription
DEPENDS_TOKENBearer token
DEPENDS_NAMESPACEDefault namespace
DEPENDS_API_URLAPI base (e.g. http://localhost:3000/v1)
DEPENDS_CONFIGConfig path

Upgrading

CLI:

depends update  # git pull + bun install in ~/.config/depends/src

Server:

  1. Backup: cp data/depends.db data/depends.db.backup.
  2. git pull && bun install.
  3. Restart: systemctl restart depends.

Schema auto-applies new tables/indexes. For column changes:

  1. Stop server.
  2. Backup DB.
  3. sqlite3 data/depends.db < migration.sql.
  4. Update code, restart.

No migrations needed currently. Events purge after 30 days (data-purging.md).

Recent changes