CLAUDE.md now carries only what must be known *before* opening a file: hard rules, gotchas, and an entry-point table. Everything descriptive moved to the doc that lives next to the code. Moved out: - stack versions, plugin roles, asset pipeline, nav shape, user/ repo tracking rules → docs/reference/architecture.md - Playwright layout, config facts, auth-setup project, test account → docs/reference/testing.md (new) - folder map, full make command list (build/test/demo/worktree targets that only existed in CLAUDE.md) → README.md - dev/prod Twig settings table → already in docs/guides/deploy-cycle.md Fixed while verifying, all of them descriptions that had drifted: - demo fixtures were listed as italy-2026-demo + no-photos-demo; the actual folders are italy-2025 + italy-2026-demo - the map engine was cited at js/src/maplibre-utils.js; it is js/maplibre-utils.js, a hand-authored file beside the bundles - the build-output list omitted fonts/ and the generated templates/partials/weather-icons.html.twig, and did not flag that js/maplibre-utils.js and js/nav.js are sources living in js/ - README called user/ a "standalone git repo" (it is a submodule) - docs/README.md linked to a non-existent working/production-todo.md - git-sync-notes.md pointed at "CLAUDE.md §1", a section number that no longer exists Net: ~17.1k → ~8.5k chars of always-loaded context. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
89 lines
4.9 KiB
Markdown
89 lines
4.9 KiB
Markdown
# Git Sync Plugin — Setup Notes
|
|
|
|
## ⚠️ Config lives in the ENVIRONMENT tree, not `user/config/` (IMPORTANT)
|
|
|
|
Prod has a per-environment override directory `user/env/<hostname>/config/`
|
|
(created for Twig prod-mode — see [`../guides/deploy-cycle.md`](../guides/deploy-cycle.md) →
|
|
"The env override tree"). **A crucial Grav side effect:
|
|
once that env dir exists, the Admin panel saves ALL config changes — system and
|
|
plugin — into the active environment's config tree**, not `user/config/`.
|
|
|
|
So on prod, `git-sync.yaml` (configured via Admin) lives at:
|
|
|
|
```
|
|
user/env/intotheeast.com/config/plugins/git-sync.yaml ← here (env tree)
|
|
user/config/plugins/git-sync.yaml ← NOT here
|
|
```
|
|
|
|
Why this matters:
|
|
|
|
- **⚠️ `user/env/` is NOT safe unless gitignored — it is NOT scoped out by the
|
|
`folders` setting.** An earlier version of this note claimed `user/env/`
|
|
"never reaches Gitea" because it is outside git-sync's synced folders. **That
|
|
is wrong and caused a live secret leak (2026-07-05).** git-sync's auto-commit
|
|
stages files *outside* the configured `folders`; on prod it pushed the whole
|
|
`user/env/intotheeast.com/config/` tree — JWT secret, CSRF salt, **and the
|
|
git-sync token + webhook secret** — to Gitea. The fix was to **gitignore
|
|
`/env/`** (commit `6e8eadb`). So: prod Admin config edits stay server-only
|
|
*only because `/env/` is now gitignored*, not because of folder scope. Author
|
|
durable config in the repo, not prod Admin. Full analysis:
|
|
`docs/solutions/architecture-patterns/git-sync-secret-exposure-and-tracked-file-boomerang.md`.
|
|
- **Look in both places.** When inspecting/toggling server config, check
|
|
`user/config/plugins/<name>.yaml` **and**
|
|
`user/env/<host>/config/plugins/<name>.yaml` (env wins).
|
|
- **Tooling is env-path-aware.** `scripts/git-sync-toggle.sh` takes a `WEBROOT`
|
|
and searches `user/env/*/config/plugins/git-sync.yaml` first, then
|
|
`user/config/plugins/git-sync.yaml`. `make remote-git-sync-disable/enable-<env>`
|
|
and `make remote-diag-<env>` use it.
|
|
|
|
## Folders format
|
|
|
|
Older plugin versions' UI saved the `folders` field as a single comma-string
|
|
(`- 'pages,config,themes'`), which the plugin iterated as one path, so sync
|
|
silently did nothing. **git-sync v3.4.4 (installed on prod 2026-07-04) saves it
|
|
correctly** as separate list items:
|
|
|
|
```yaml
|
|
folders:
|
|
- pages
|
|
- config
|
|
- themes
|
|
```
|
|
|
|
If you see the comma-string form on an older version, fix it by editing
|
|
`git-sync.yaml` directly (at whichever path it lives — see above); do not
|
|
re-save folders via the Admin UI on the buggy version.
|
|
|
|
## Per-install / secret files — must be gitignored (gitignore is the boundary)
|
|
|
|
git-sync's auto-commit stages **everything under `user/` that is not
|
|
gitignored** — the `folders` setting does *not* scope the commit add-set (a
|
|
2026-07-05 leak proved this by pushing `user/env/**`, outside the configured
|
|
folders). So `.gitignore` — not folder scope — is the only thing keeping a
|
|
per-install or secret file off Gitea. Keep all of these gitignored in
|
|
`user/.gitignore`:
|
|
|
|
| Path | Why |
|
|
|---|---|
|
|
| `env/` | **whole per-host env tree** — holds the live git-sync token, JWT secret, CSRF salt + all server-side Admin config. Gitignored + untracked 2026-07-05 (commit `6e8eadb`) after it leaked to Gitea. NOT safe on folder scope alone. |
|
|
| `config/plugins/git-sync.yaml` | encrypted token; server-specific (also lives at env path on prod) |
|
|
| `config/plugins/api-private.php` | API JWT secret |
|
|
| `config/security.yaml` | Grav nonces/salts (legacy location) |
|
|
| `config/versions.yaml` | per-install Grav schema-migration state — differs per env (dev 2.0.4, prod 2.0.7); Grav regenerates it. Untracked 2026-07-04. |
|
|
| `config/security-private.php` | CSRF/nonce + admin rate-limit signing salt; gitignored + untracked 2026-07-05 (commit 2840018). Each env keeps its own; untracking regenerates prod's salt (one-time admin re-login). |
|
|
|
|
> **Why a key inside a *tracked* config file (e.g. `popularity.salt` in `api.yaml`) can't just be stripped** — it regenerates at runtime and boomerangs back via git-sync's `git add -A`. See `docs/solutions/architecture-patterns/git-sync-secret-exposure-and-tracked-file-boomerang.md` for the full round-trippable-set model.
|
|
|
|
## git-sync config summary (prod, 2026-07-04)
|
|
|
|
- `repository: https://git.gorinskat.nl/m038/intotheeast-com-content.git`,
|
|
`branch: main`, HTTPS + token auth (SSH is Tailscale-only).
|
|
- `sync.direction: both`, `on_save/on_delete/on_media: true` → prod Admin edits
|
|
and `/post` push to Gitea; content-repo pushes pull to prod **via webhook**
|
|
(`/_git-sync`). The webhook is configured in Gitea repo settings (same secret
|
|
as the test instance).
|
|
- **Before enabling on a fresh server**, reset the synced folders clean
|
|
(`make remote-fetch-content-<env>`) so no install-time drift (e.g. a stale
|
|
`versions.yaml`) gets pushed on the first sync. Toggle with
|
|
`make remote-git-sync-disable/enable-<env>`.
|