Establish dev workflow (feature-branch→main) and pull Gitea bootstrap earlier

- Add CONTRIBUTING.md: interim local-git rules (no work on main; every change
  a feature branch merged into main) and the target state (Gitea-hosted repos,
  GitOps source cutover, CI/CD via Gitea Actions running the Kyverno gate +
  Chainsaw conformance Job, PR merge gate). Note the self-hosted-git
  bootstrapping circularity + off-cluster mirror/backup mitigation.
- AGENTS.md: add section 12 (version-control workflow).
- docs/05: source-of-truth migration (local bootstrap -> self-hosted Gitea).
- docs/13 + roadmap: reprioritize Gitea as bootstrapping-critical, onboarded
  early (WS-APPS step 2); nextcloud onboarding split out.
- task-board: T-6.1a (gitea early), T-6.1b (source+CI migration to Gitea).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-15 22:40:11 -05:00
1 parent e8c555cfeb
commit de26a53d4b
8 files changed
+126 -6

No files matched your search

+22
View File
@@ -80,6 +80,28 @@ Full detail and the "is an automated commit a GitOps change?" nuance is in
- Because desired state is in git and data is on Longhorn/backups, a rebuilt cluster reconverges by
re-bootstrapping Flux and restoring volumes ([04](04-storage-and-state.md)).
## Source-of-truth: local bootstrap → self-hosted Gitea
The platform hosts its own git, which creates a deliberate bootstrapping sequence
([`../CONTRIBUTING.md`](../CONTRIBUTING.md)):
1. **Bootstrap source.** Initially there is no remote git on this network (the prior `home-network`
Gitea is gone from here). Development is local; the cluster is first reconciled from a
**bootstrap source** (this local repo / an out-of-band source).
2. **Gitea comes online early.** **Gitea is one of the first services onboarded** ([13](13-service-catalog.md))
so the platform gains its own git host at `gitea.home.keithjackson.dev`.
3. **Cut Flux over to Gitea.** Once Gitea is stable, Flux's `GitRepository` source is migrated from
the bootstrap source to Gitea; the platform then reconciles from its own git.
4. **CI/CD moves to Gitea Actions.** The Kyverno L0 policy gate and the trigger for the in-cluster
Chainsaw conformance Job ([14](14-testing-and-conformance.md)) run as Gitea Actions pipelines on
push/PR; PRs become the enforced merge gate into `main`.
**Circularity & DR.** Gitea runs *on* the cluster Flux reconciles *from* Gitea. Mitigations:
- Keep an **off-cluster mirror** of the platform repo so a source-of-truth exists that outlives the
cluster.
- Treat **Gitea as DR-critical**: its repos/DB are backed up off-cluster ([04](04-storage-and-state.md)),
so a cluster loss never loses the git history needed to rebuild the platform.
## Guardrails
- No `kubectl apply` of app state by hand — everything flows through git/Flux (R-GITOPS-01, click-
ops-never per [AGENTS.md](../AGENTS.md)).
+7 -1
View File
@@ -75,7 +75,7 @@ Egress and dependencies below are **normative intent**; implementers render the
| 9 | **unifi** | container | internal | internet | config: longhorn | — | UniFi network controller |
| 10 | **semaphore** | container | internal | internet | config/db: longhorn | — | Ansible UI |
| 11 | **kasm** | container | internal | internet | config: longhorn | — | Kasm Workspaces (may need more resources; container-first, VM if required) |
| 12 | **gitea** | container | public | internet | repos/db: longhorn (irreplaceable → backed up) | — | Git hosting; DR-critical |
| 12 | **gitea** | container | public | internet | repos/db: longhorn (irreplaceable → backed up) | — | Git hosting; **bootstrapping-critical** — self-hosts the platform's GitOps source + CI/CD; onboarded **early** (see below); DR-critical (off-cluster backup + mirror) |
| 13 | **qbittorrent** | container | internal | **vpn** | config: longhorn; downloads: **bulk** | ← sonarr, ← radarr | VPN + kill-switch; download client |
**VPN-class set (R-NET-05/06):** sonarr, radarr, jackett, qbittorrent — all egress via VPN with an
@@ -103,6 +103,12 @@ and inherit all guarantees automatically — that is the point of the abstractio
([09](09-dns-and-ingress.md)); everything else stays `internal`.
- **Kasm** is resource-heavy and may be a candidate for `kind: vm` if container mode proves
insufficient — the ServiceDefinition makes that a one-field change.
- **Gitea is bootstrapping-critical.** The platform self-hosts its git and CI/CD, so Gitea is brought
online **early** (WS-APPS step 2, right after PiHole). Once stable, the GitOps source and CI move
from the local bootstrap source to Gitea + Gitea Actions ([05](05-gitops-and-delivery.md),
[`../CONTRIBUTING.md`](../CONTRIBUTING.md)). Because a cluster loss would take its own git host with
it, Gitea's repos/DB are backed up **off-cluster** and mirrored, so the platform can always be
rebuilt from a source that outlives the cluster.
## Acceptance gates
- Each service is fully wired from its ServiceDefinition alone (compute, storage, policy, egress,