Documentation · Installation

Prepare to install OpenMOM

A pnpm workspace of TypeScript packages against a PostgreSQL database with row-level security. The public repository and local installation open in January 2027.

Prerequisites

  • Node.js 22+ — the workspace engines require node >=22.
  • pnpm 10 — the repo pins pnpm@10.33.0 via packageManager; run corepack enable and it activates automatically.
  • Docker + Docker Compose — used to run the PostgreSQL 16 container. No other services are required.

Repository access

Coming January 2027.

The repository will open as soon as OpenMOM is fully tested, reaches 100% parity with MOM 10, and delivers improvements beyond the legacy system. The remaining steps document the launch setup.

Start Postgres

pnpm db:up      # docker compose up -d postgres

The compose file runs postgres:16-alpine with a named volume and a health check, published on 127.0.0.1:5434. The host port is deliberately 5434 — development machines often already run Postgres instances on 5432 and 5433, and a second Postgres silently failing to bind is a classic time sink.

One subtlety worth knowing: the container publishes on IPv4 only, so localhost can intermittently resolve to ::1 first and fail with ECONNREFUSED. The example connection strings pin 127.0.0.1 instead of localhost — keep that.

Configure the environment

Copy .env.example to .env at the repository root. The defaults match the compose file exactly:

Variable Example Purpose
DATABASE_URL postgres://openmom:openmom@127.0.0.1:5434/openmom Migrations, CLI, and platform-side tooling. Connects as the openmom superuser.
OPENMOM_APP_URL postgres://openmom_app:openmom@127.0.0.1:5434/openmom All application traffic. Connects as the restricted openmom_app role.
OPENMOM_TEST_URL postgres://openmom:openmom@127.0.0.1:5434/openmom_test Test database used by the test suites.
OPENMOM_TEST_APP_URL postgres://openmom_app:openmom@127.0.0.1:5434/openmom_test App-role connection for the test database.

OpenMOM's tooling resolves configuration through projectEnvValue() (packages/schema/src/env.ts), which reads the repo-root .env first, then the ambient environment, then falls back to a local default. The repo-root file deliberately beats a shell-exported DATABASE_URL — your shell may export one for an unrelated project, and pointing migrations at the wrong database is not a recoverable mistake.

Why two roles

The app role and row-level security

Migration 0017 creates openmom_app with NOSUPERUSER and NOBYPASSRLS. Every tenant-scoped table carries a tenant_id and runs with ENABLE + FORCE ROW LEVEL SECURITY; the API sets app.tenant_id per transaction, and Postgres itself refuses to return another tenant's rows. The openmom superuser bypasses RLS entirely, which is why the API's pool requires OPENMOM_APP_URL and fails hard without it — a superuser connection would silently disable tenant isolation.

Run the migrations

pnpm migrate           # OSS schema stream (tracker: schema_migrations)
pnpm migrate:cloud     # OSS stream + commercial stream (self-hosters: not needed)

The schema lives in packages/schema/migrations/ as numbered SQL files applied in order and tracked in schema_migrations. Migrations are additive — upgrades never rewrite history. The commercial stream (billing, usage metering, platform RBAC) is only used by the managed cloud edition; self-hosted deployments only need pnpm migrate.

Verify

pnpm typecheck     # TypeScript across the workspace
pnpm test:oss      # OSS test suites (uses OPENMOM_TEST_URL)

When the tests can connect to the test database, you're set. Next: seed the demo company and start the apps →