Running it
Rails runs on the host. Postgres, OpenSearch, MinIO and Mailpit run in Docker (compose.yml). The
analyzers shell out to native binaries, which is why the app itself is not containerised in
development.
brew bundle # native dependencies the analyzers needbin/setup # services, database, seed, generated API typesbin/dev # web, worker, vite, and the two codegen watchersServices
Section titled “Services”| Service | Image | Host port |
|---|---|---|
| postgres | postgres:17-alpine |
5434 |
| opensearch | opensearchproject/opensearch:2.11.0 |
9201 |
| minio | minio/minio |
9000, console 9001 |
| mailpit | axllent/mailpit |
1025, UI 8025 |
db/docker-entrypoint-initdb.d creates a non-superuser role for the application. A superuser
bypasses row-level security unconditionally — see Tenancy.
Tenants are subdomains
Section titled “Tenants are subdomains”bin/setup seeds two. Add them to /etc/hosts:
127.0.0.1 things.test demo.things.test acme.things.testThen demo.things.test:4242 and
acme.things.test:4242. The suffix is THINGS_HOST_SUFFIX
(things.test) and the port is PORT (4242).
Two tenants exist from the first seed so that every scenario in the suite can be exercised against both.
What bin/dev runs
Section titled “What bin/dev runs”Procfile.dev:
| Process | Command |
|---|---|
| web | bin/rails server -p ${PORT:-4242} |
| vite | bin/vite dev |
| worker | bin/jobs — Solid Queue, both pools |
| schema | chokidar on app/graphql/**/*.rb → graphql:dump_schema + npm run codegen |
| codegen | chokidar on app/javascript/**/*.ts{,x} → npm run codegen |
Build products
Section titled “Build products”schema.graphql and the generated TypeScript under app/javascript/graphql/generated/ are not
committed. A clean checkout has neither, and the Vite build fails without them:
bin/rails graphql:dump_schemanpm run codegenThe suite
Section titled “The suite”bin/rails test40 test files under test/. Isolation is asserted directly in
test/models/tenant_isolation_test.rb and test/integration/graphql_tenancy_test.rb.
Before committing
Section titled “Before committing”bin/check-boundaryNothing in the repository may name a host, a domain, or a secret. The script greps tracked and
unignored files for a fixed pattern set, skipping *.md and plans/. It also runs in CI.