Skip to main content

Multi-project mode

Fairway's project boundary is the configured Fairway DB, normally one DB per git repo. A repo may host multiple Fairway configs when it intentionally tracks separate workstreams, such as an implementation track and a docs portal track. Multi-project aggregation is opt-in via a registry — there is no single shared database.

Why per-project DBs

  • The DB moves with the repo. Clone, archive, or rm -rf and state stays consistent with the working tree.
  • Schema migrations affect one project at a time.
  • A project's data is portable — copy .fairway/ to share state, or commit it for fully reproducible team setups.

Every row in every table carries a project_id column (see schema.md) — in v1 SQLite each DB has a single value, set from [fairway] project_name at DB open. This makes the schema portable to a future shared backend (Postgres) without a row-rewrite migration.

The registry

~/.fairway/registry.toml lists known projects:

[[project]]
name = "service-platform"
path = "/path/to/service-platform"
# db_path optional; defaults to <path>/.fairway/state.db
# config_path optional; recorded by fairway register for same-repo configs

[[project]]
name = "fairway"
path = "/path/to/fairway"

The registry is the only file outside of a project's own directory that fairway writes. Plain TOML; editing by hand is fine.

Commands

  • fairway register [--name <n>] — add the current project. Name defaults to [fairway] project_name or the repo basename. Idempotent for the same name/path/DB/config identity.
  • fairway unregister [<name>] — remove. Defaults to the current project.
  • fairway projects — list registered projects with last-activity timestamp.

Project name

Each project carries a project_name, used to label rows in the multi-project dashboard:

[fairway]
project_name = "service-platform" # default: basename of the repo root

Names must be unique across the registry. fairway register refuses duplicate names for different identities, and refuses duplicate path/DB/config identities under different names. It allows multiple entries with the same repo path when their names and DB/config identities differ.

For same-repo multi-config work, register each config explicitly:

cd /path/to/service-platform
fairway --config .fairway/platform-config.toml register --name service-platform
fairway --config .fairway/docs-config.toml register --name service-docs
fairway projects
fairway dashboard start --multi --read-only --listen 127.0.0.1:7878

The registry records both db_path and config_path, so /projects, board filters, wall project groups, activity labels, and exports can distinguish same-path projects by project name and backing DB.

Dashboard modes

fairway dashboard runs single-project mode against the current repo's DB. This is the common case.

fairway dashboard --multi runs multi-project mode:

  • Opens the registry.
  • ATTACH DATABASE each registered DB into a single SQLite session.
  • Read views UNION ALL across attached DBs. Each row already carries project_id — no need to project it from config.
  • The wall lanes strip groups lanes under project headers.
  • /board exposes the project selector as URL-backed project filter state and an active project filter chip.
  • /reports aggregates registered project DBs into a read-only cross-project activity rollup. It keeps duplicate task ids distinct with a project label and supports project, profile, role, tag, status, date range, and evidence-type filters.
  • If a registered project DB cannot be opened, multi-project dashboard startup keeps serving available projects and shows the unavailable registry entry in /projects and /reports with its open error.
  • The activity feed prefixes entries with [project] .

Single-project and multi-project queries share the same Go view layer; the multi-project path swaps the data source.

Why per-DB instead of one shared local DB

project_id is in the schema, so a single shared local SQLite would be technically possible. We choose per-DB anyway because:

  • Schema migrations stay per-project; one project's upgrade does not block another's.
  • The DB moves with the repo (clone, archive, rm -rf are all consistent).
  • Backup is per-project; you can hand a colleague one .fairway/ directory without leaking other projects.
  • Bug blast radius is bounded — a corrupt DB takes down one project, not all of them.

The shared-DB story is for a server-hosted (Postgres) future, not a shared local SQLite file.

Path to a shared server

When (if) fairway grows a Postgres adapter:

  • One Postgres DB holds many project_id values.
  • Existing local SQLite DBs are imported with fairway export | fairway import --to postgres://... — rows carry their project_id intact.
  • The CLI's [fairway] backend = "postgres://..." setting switches the store driver. No schema change, no row rewrite.

Performance

A registry of 20 projects with 1000 tasks each (~20MB of attached state, 20k task rows) is well within multi-project dashboard budgets. Beyond that, multi-project mode degrades to slower first-paint but stays usable. Single-project mode is unaffected by registry size.

Limits

  • Multi-project mode is read-only. Mutations always target one project's DB via the CLI inside that project's directory.
  • The registry does not enforce that all attached DBs share a schema version; mismatched versions are flagged in the dashboard header so the user can run fairway db migrate per project.