Synced verbatim from
fornax-coreat build time — edit it there, not here.
ADR 0002: Repository, CI, and environment-isolation conventions
Status: Accepted
Date: 2026-08-28
Jira: FORNX-22/FORNX-23, informed by survey of ~/Bryant-Developments/horonomy/*
Context
The epic requires Fornax's Neon/GCP/CI conventions to match "existing Horonom
product conventions." A survey of octans/ophiuchus/circinus/
official-website found two divergent real precedents; this ADR picks one
per concern and records why, so it isn't re-derived per ticket.
Decisions
GitHub organization and repository topology (FORNX-21)
Fornax is a Horonomy product. Canonical org: horonomy
(https://github.com/horonomy) — no dedicated Fornax GitHub organization.
fornax-core was bootstrapped under a personal account and transferred via
native GitHub repository transfer once this was confirmed (2026-08-29),
preserving history/PRs/branches/tags.
Repository topology under horonomy:
Horonomy GitHub organization
├── fornax-core PUBLIC (this repo — local Rust runtime, adapters, CLI)
├── fornax-cloud PRIVATE (ingest, backend, SaaS frontend)
├── fornax-docs PUBLIC (technical documentation)
├── fornax-website PUBLIC (marketing/product site)
└── fornax-infra PRIVATE (Terraform, deployment config)
fornax-cloud/fornax-docs/fornax-website/fornax-infra are created when
their corresponding tickets actually need them — not speculatively. Always
verify the current ticket key live in Jira before citing it here; this ADR
has twice recorded a stale FORNX-
CI
Per-build-unit, path-filtered GitHub Actions workflows (not one monolith):
ci.yml (fmt/clippy/test, matches circinus's pattern), later a separate
infra.yml (terraform fmt/validate only — no apply credentials in CI) and a
workflow_dispatch-only relay-deploy.yml once Beta infra exists (FORNX-35+).
Third-party actions pinned by commit SHA. permissions: contents: read
default. No push-to-deploy for infra — deploy workflows are manual dispatch
only, per ophiuchus's ADR-0010 amendment (this was a deliberate correction
there after an unattended-apply incident risk was identified).
Docs — distributed authoring, centralized publishing (superseded 2026-08-29)
Originally this ADR picked the circinus/ophiuchus precedent — one
Docusaurus site per product, no central aggregator repo. Superseded by an
explicit owner directive (2026-08-29): Fornax uses a dedicated
horonomy/fornax-docs repo (public) that owns the Docusaurus shell, theme,
navigation, and centralized build/publish, aggregating content authored
close to the code (fornax-core/docs/**, fornax-cloud/docs/public/**) —
"distributed authoring + centralized publishing" as the epic originally
specified, not the single-site precedent.
Hosting stays reconciled with the rest of this ADR's one-domain-per-product
convention: the canonical URL is still fornax.horo.run/docs (no separate
docs.* subdomain), it's just that the content serving that path is now
built and owned by a separate repo rather than living inside
fornax-website's own codebase. The actual routing (reverse proxy /
Cloudflare path rule from fornax.horo.run/docs to the fornax-docs
deploy) is Beta-infra work (FORNX-43, Cloudflare domain topology) and is not
implemented yet — recorded here as the intended hostname, not a live deploy.
fornax-docs was created and its MVP content shipped under FORNX-45.
Terraform / environment isolation
Folder-per-environment (infra/envs/beta/, infra/envs/prod/), separate GCP
projects, separate GCS state buckets, workflow_dispatch-only deploys via
GitHub Environments, images digest-pinned, auth via Workload Identity
Federation (no service-account JSON keys) — matches both ophiuchus and
circinus. No decision needed; both repos agree here.
Neon Postgres
The epic is explicit: one Neon project, environment isolation by branches
(matches ophiuchus's pattern, not circinus's later two-project reversal).
Followed as specified — circinus's two-project reasoning (a leaked
project-scoped API key can reach every branch) is noted for awareness but not
adopted; if Fornax's Beta credential surface later proves as sensitive as
circinus's billing/webhook surface, revisit via a new ADR, not silently.
Repo layout
src-equivalent is crates/ (Rust workspace, not src/ — Rust convention
takes precedence over the Python-repo precedent here). docs/adr/NNNN-kebab-title.md
(MADR-lite, matches all four precedent repos). .claude/CLAUDE.md +
AGENTS.md (pointer only) + README.md — same four-file precedence chain
used across Horonom repos.
Commits / branches
Gitmoji + scoped imperative subject (✨ (scope): Description), matching
observed circinus git log and the global CLAUDE.md commit policy. Branch
naming v0.0.1/FORNX-<n>/<type>/<snake_case_slug>, matching the Horonom
family's v<version>/<TICKET>/<type>/<slug> pattern. PR-only to main.
Consequences
- FORNX-45 (Docs) uses a dedicated
fornax-docsrepo per the 2026-08-29 owner directive (superseding this ADR's original single-site stance); canonical hostname staysfornax.horo.run/docs, routing not yet deployed. - FORNX-37 (Neon) uses one project + branches per the epic; the alternative two-project pattern is documented here as a known trade-off, not adopted.