Config: .env = projects root only; derive each project's forge from git
Reduce .env to just REPOS_HOST_PATH (the projects root); runtime bootstrap moves to compose/defaults. Projects are the subdirectories of the single root — removed the project-directories feature (store table, service methods, /api/config/project-dirs, Settings section). Each project's forge is derived from its git remote (matched to a configured forge, else the bare host) and shown as a pill next to its name (State.Forge via scanner ForgeFor + svc.ForgeDisplay). Removed first-run .env seeding; forges + identity are managed in Settings. Added forge.HostOf. AGENT.md updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -124,7 +124,7 @@ values** rather than reintroducing hardcoded hex.
|
||||
- **Git stays the system of record for repository data** — never mirror repo
|
||||
contents into another store. The one sanctioned datastore is the **config store**
|
||||
(§1.5): a private SQLite DB holding *app configuration* (forge hosts + tokens,
|
||||
the project directories to scan, git identity), not git data. Anything beyond
|
||||
git identity), not git data. Anything beyond
|
||||
that (mirroring repo/PR data, a server‑side app DB) still requires asking first.
|
||||
Per‑user UI state remains in browser `localStorage` (§4).
|
||||
|
||||
@@ -146,22 +146,24 @@ must be treated as such:
|
||||
|
||||
### 1.5 Configuration: bootstrap `.env` + a private config store
|
||||
|
||||
Configuration is split:
|
||||
Configuration is split three ways:
|
||||
|
||||
- **Bootstrap `.env`** — only what's needed to start the process and can't live in
|
||||
the DB: listen address, TLS, `APP_ENV`, `LOG_FILE`, the `git` binary, scan
|
||||
tuning (interval/depth/ignore/fetch), and the **config DB path**. A committed
|
||||
`.env.example` documents every variable; **never commit a real `.env`**.
|
||||
- **Config store (`internal/store`, SQLite)** — the domain config that used to
|
||||
live in `.env`: **forge hosts + access tokens, the project directories to scan,
|
||||
and the git commit identity.** Managed at runtime in the app's **Settings**
|
||||
(`/settings`), not by editing files. On first run with an empty DB it is
|
||||
**seeded** from the `.env` values (`GITEA_*`, `GIT_REPO_ROOTS`, `GIT_USER_*`);
|
||||
after that those `.env` values are ignored.
|
||||
- **The DB must not be reachable outside the container.** It lives on a **private
|
||||
named Docker volume** (`/data`) — never bind‑mounted into the project, never on a
|
||||
published port. Tokens are stored there relying on that isolation. Never hardcode
|
||||
tokens/hosts/paths in code.
|
||||
- **`.env` — the projects root, and nothing else.** The only value a user sets in
|
||||
`.env` is `REPOS_HOST_PATH`: the host directory that holds their projects, mounted
|
||||
into the container as the single **projects root** (`PROJECTS_ROOT`, default
|
||||
`/repos`). **Each project is a subdirectory of that root.** `.env` is git‑ignored;
|
||||
a committed `.env.example` documents it.
|
||||
- **Runtime bootstrap — compose/env defaults, not the `.env` file.** Listen
|
||||
address, TLS, `APP_ENV`, `LOG_FILE`, the `git` binary, scan tuning, the config
|
||||
DB path, and `PROJECTS_ROOT` come from `docker-compose.yml`'s `environment:` and
|
||||
in‑code defaults — not from the user's `.env`.
|
||||
- **Config store (`internal/store`, SQLite)** — **forge hosts + access tokens** and
|
||||
the **git commit identity**, managed at runtime in the app's **Settings**
|
||||
(`/settings`), not by editing files. A project's **forge is derived from its git
|
||||
remote** (matched to a configured forge) — not stored per project (§8.4). The DB
|
||||
must not be reachable outside the container: it lives on a **private named Docker
|
||||
volume** (`/data`) — never bind‑mounted, never on a published port; tokens rely on
|
||||
that isolation. Never hardcode tokens/hosts/paths in code.
|
||||
|
||||
### 1.6 Everything runs in Docker / docker‑compose
|
||||
|
||||
@@ -227,7 +229,7 @@ without asking.
|
||||
│ └── server/main.go # entrypoint: wire config, git, scanner, router
|
||||
├── internal/
|
||||
│ ├── config/ # bootstrap .env loading, typed config struct (§1.5)
|
||||
│ ├── store/ # SQLite config store: forges+tokens, project dirs, identity (§1.5)
|
||||
│ ├── store/ # SQLite config store: forges+tokens, git identity (§1.5)
|
||||
│ ├── git/ # THE Git boundary: interface + os/exec impl (all git ops)
|
||||
│ ├── repos/ # discovery, in-memory index/cache, refresh scanner worker
|
||||
│ ├── service/ # the ONE service layer both the HTTP API and MCP call (§1.7)
|
||||
@@ -456,6 +458,10 @@ later behind the same interface).
|
||||
matching the forge features are simply absent (**graceful degradation**). The
|
||||
service resolves a repo → provider by matching remotes (preferring `origin`)
|
||||
against the stored forges, caching a client per host.
|
||||
- **A project's forge is derived from git, not stored per project.** The scanner
|
||||
reads each repo's `origin` remote and labels it with the matching configured
|
||||
forge's name (or the bare host when unmatched); the dashboard shows that label
|
||||
next to the project name (`repos.State.Forge`, via `svc.ForgeDisplay`).
|
||||
- The provider is inferred from a repo's remote URL. Never send repo data to a
|
||||
host the user didn't configure.
|
||||
|
||||
@@ -540,16 +546,16 @@ component carries its own context.
|
||||
*(Claude Code: surface these to the human at the first relevant moment; don't
|
||||
silently guess.)*
|
||||
|
||||
- ✅ **RESOLVED 2026-09-22:** **Domain config moved from `.env` to a private
|
||||
SQLite store** (`internal/store`, §1.5): forges+tokens, project directories, git
|
||||
identity — managed in Settings (`/settings`), seeded from `.env` on first run.
|
||||
DB on a private `/data` volume (not bind‑mounted, no port). Forge is now
|
||||
**multi‑host**; git auth sets an `http.extraheader` per forge.
|
||||
- **Container mount constraint (multiple project dirs):** the container can only
|
||||
scan host paths that are **bind‑mounted at `up` time**. Today `~/Projects` is
|
||||
mounted to `/repos`, so project dirs added in Settings must resolve under a
|
||||
mounted base. A dir outside it needs a new compose mount — surface this if asked
|
||||
to add such a path.
|
||||
- ✅ **RESOLVED 2026-09-22:** **`.env` holds only the projects root; forges +
|
||||
identity live in a private SQLite store** (`internal/store`, §1.5), managed in
|
||||
Settings. **Projects are the subdirectories** of the single root
|
||||
(`REPOS_HOST_PATH` → `/repos`); each project's **forge is derived from its git
|
||||
remote** and shown next to its name. DB on a private `/data` volume (not
|
||||
bind‑mounted, no port). Forge is **multi‑host**; git auth sets an
|
||||
`http.extraheader` per forge.
|
||||
- **Mount constraint:** the container only sees host paths bind‑mounted at `up`
|
||||
time. All projects must live under the mounted root (`REPOS_HOST_PATH`); a
|
||||
project elsewhere needs its own compose mount + a widened/extra root.
|
||||
- **Token encryption at rest:** tokens are stored plaintext in the private DB
|
||||
(isolation is the control). Confirm before adding encryption‑at‑rest (a key
|
||||
would then need storing too).
|
||||
|
||||
Reference in New Issue
Block a user