Compare commits

...

3 Commits

Author SHA1 Message Date
eaf2398c7a docs(generic): document migration immutability and sequential versioning
Migrations are sequentially numbered and frozen once committed. Editing an
already-landed migration causes checksum divergence and migration-runner
failures at deploy time — new changes must go in new files. Call this out
explicitly so contributors don't quietly break a service by "fixing" a
prior migration in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:36:52 +03:00
e9447f54f4 docs(generic): note Postgres MCP server availability for agentic contributors
Projects with a Postgres dependency typically expose an MCP server scoped
to their database(s). Call this out so agents know to verify schema and
query shapes against the real database rather than guessing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:34:37 +03:00
4f66508d86 docs(generic): document Gitea (git.lair.cafe) as default source host
Note that new projects default to the self-hosted Gitea instance at
git.lair.cafe (git.internal on the WireGuard mesh), that legacy projects
on GitHub/GitLab are being migrated as they come up for refactor, and
that relocated repos should carry a prominent pointer to the new URL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:32:10 +03:00

View File

@@ -180,8 +180,11 @@ Default for any app with a central data store.
- Connection is **mTLS with passwordless auth**. Host-level client certificates issued by the internal step-ca, with cert CN → pg role mapping via `pg_ident.conf`. - Connection is **mTLS with passwordless auth**. Host-level client certificates issued by the internal step-ca, with cert CN → pg role mapping via `pg_ident.conf`.
- No passwords in config files, ever. Connection strings reference cert paths. - No passwords in config files, ever. Connection strings reference cert paths.
- Migrations via `sqlx-cli` or `refinery`; migration files live in `crates/<app>-data/migrations/`. - Migrations via `sqlx-cli` or `refinery`; migration files live in `crates/<app>-data/migrations/`.
- **Migrations are sequentially versioned and immutable once committed.** File naming follows the tool's convention (`V0001__init.sql`, `V0002__add_users.sql`, … for refinery; `0001_init.sql`, `0002_add_users.sql`, … for sqlx). Each new schema change lands as a **new** file with the next sequence number — **never** edit a migration that has already been committed, even if it hasn't been deployed yet, because checksums diverge and the migration runner will refuse to start (or worse, leave production out of sync with dev).
- Schema changes are forward-only in production. Destructive migrations require a dedicated maintenance window and an explicit plan. - Schema changes are forward-only in production. Destructive migrations require a dedicated maintenance window and an explicit plan.
- If you catch a bug in a recently-added migration *before* it's been merged or deployed anywhere, amending is fine — but the moment it's landed on `main` or run against any database, treat it as frozen and write a follow-up migration to correct the mistake.
- Use `sqlx` with compile-time query checking (`sqlx prepare`) and commit the generated `.sqlx/` offline query cache so CI builds don't need a live database. - Use `sqlx` with compile-time query checking (`sqlx prepare`) and commit the generated `.sqlx/` offline query cache so CI builds don't need a live database.
- **Agentic contributors working in a project with a Postgres dependency will usually have MCP access to a Postgres MCP server scoped to that project's database(s).** Prefer using the MCP server to inspect schema, verify query shapes against real tables, and sanity-check migrations before applying them — don't guess at column names or types when you can look them up. The scope is limited to the project's own databases; don't assume access to unrelated ones.
### Distributed database: Turso ### Distributed database: Turso
When the app's data model is distributed (edge replicas, per-site local copies with sync), use Turso. Auth via Turso-issued tokens stored in the per-host secret store, not in `manifest.yml`. When the app's data model is distributed (edge replicas, per-site local copies with sync), use Turso. Auth via Turso-issued tokens stored in the per-host secret store, not in `manifest.yml`.
@@ -476,6 +479,12 @@ This is the environment these apps deploy into. Claude Code should assume it.
- SELinux enforcing per §10. - SELinux enforcing per §10.
- Podman quadlets for containerised workloads; bare-metal systemd units for native Rust binaries (preferred where feasible). - Podman quadlets for containerised workloads; bare-metal systemd units for native Rust binaries (preferred where feasible).
### Source hosting
- **New projects are hosted on the self-hosted Gitea instance** at `git.lair.cafe` (or `git.internal` on the WireGuard mesh — both resolve to the same instance). Agentic contributors will usually have MCP access to this Gitea and should prefer it over any public forge when creating repos, issues, or PRs.
- **Legacy projects** live under various GitHub / GitLab orgs tied to my public username (`grenade`). These will continue to exist but are being migrated to Gitea over time, especially when they come up for a refactor.
- **When a project has been relocated**, the original public repo should carry a prominent notice at the top of its `README.md` (or a GitHub archival notice) pointing to the new Gitea URL. If you're working in a repo that looks stale or superseded, check for such a notice before assuming it's still the canonical location.
- Default to `git.lair.cafe` / `git.internal` for new scaffolds. Only push a new project to GitHub/GitLab if there's a specific reason (OSS visibility, CI integration that only the public forge offers, etc.) — and note the reason in the project README.
--- ---
## 12. Code Quality and Tooling ## 12. Code Quality and Tooling
@@ -532,4 +541,5 @@ When scaffolding or extending a project:
11. SELinux stays enforcing. Work with the default policy first; ship a custom module only when necessary (§10). Never suggest `setenforce 0`. 11. SELinux stays enforcing. Work with the default policy first; ship a custom module only when necessary (§10). Never suggest `setenforce 0`.
12. Prefer fewer dependencies. Prefer bare-metal systemd over containers unless there's a reason. 12. Prefer fewer dependencies. Prefer bare-metal systemd over containers unless there's a reason.
13. Commit in Conventional Commits syntax. Commit autonomously when the work is done; hold off when follow-ups on the same topic are likely (§12 Commits). 13. Commit in Conventional Commits syntax. Commit autonomously when the work is done; hold off when follow-ups on the same topic are likely (§12 Commits).
14. When unsure, ask — these preferences are defaults, not mandates, but deviations should be deliberate. 14. Default new repos to `git.lair.cafe` / `git.internal` (self-hosted Gitea). Public forges only with a stated reason (§11 Source hosting).
15. When unsure, ask — these preferences are defaults, not mandates, but deviations should be deliberate.