Compare commits
17 Commits
sdlc-updates
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d39685451 | |||
| 36310c48db | |||
| 738f5d8f05 | |||
| cffa73cd97 | |||
| cd5d9c5614 | |||
| 6e0e29f374 | |||
| f69319e270 | |||
| deb507714b | |||
| 40f8153c86 | |||
| 4df9637518 | |||
| 11fd2a4c34 | |||
| d6b13fa58d | |||
| c756b16c7c | |||
| 743e913126 | |||
| a0ae03e959 | |||
| 643d9e8956 | |||
| 93927ea402 |
@@ -3,8 +3,9 @@ name: coding-standards
|
|||||||
description: >
|
description: >
|
||||||
Engineering quality bar for GroomBook code: priority ordering of correctness
|
Engineering quality bar for GroomBook code: priority ordering of correctness
|
||||||
vs. clarity vs. maintainability vs. performance vs. elegance, PR and test
|
vs. clarity vs. maintainability vs. performance vs. elegance, PR and test
|
||||||
requirements, no-hardcoded-values rules, branch discipline, and the no-self-
|
requirements, no-hardcoded-values rules, branch discipline, and the
|
||||||
merge contract.
|
no-self-merge contract. The uat→main merge-gate policy lives in the `sdlc`
|
||||||
|
skill, not here.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Coding Standards
|
# Coding Standards
|
||||||
@@ -24,7 +25,7 @@ When making technical decisions, prioritize in this order:
|
|||||||
## Pull request discipline
|
## Pull request discipline
|
||||||
|
|
||||||
* All changes go through a PR. **Never push directly to `dev`, `uat`, or `main`.**
|
* All changes go through a PR. **Never push directly to `dev`, `uat`, or `main`.**
|
||||||
* No agent merges their own PR.
|
* Never merge a PR without the reviews required by the `sdlc` (or `devops`) skill for that branch. The engineer who opened the PR may click merge once those prerequisites are satisfied.
|
||||||
* Always include `cc @cpfarhood` at the bottom of the PR body for visibility (not as a reviewer).
|
* Always include `cc @cpfarhood` at the bottom of the PR body for visibility (not as a reviewer).
|
||||||
|
|
||||||
## Test requirements
|
## Test requirements
|
||||||
@@ -57,6 +58,10 @@ All releases use CalVer (`YYYY.MMDD.PATCH`, e.g. `2026.0504.0`). No SemVer, no c
|
|||||||
|
|
||||||
Push to `git.farh.net` only. Never Docker Hub for first-party images.
|
Push to `git.farh.net` only. Never Docker Hub for first-party images.
|
||||||
|
|
||||||
|
## uat→main merge-gate policy
|
||||||
|
|
||||||
|
The uat→main merge-gate policy lives in the `sdlc` skill, not here. The one-line summary: the engineer self-merges a uat→main PR once the four pre-gates (QA, UAT deploy, UAT regression, security) are green and the CEO code review is APPROVED on the Paperclip issue. A CTO Gitea Approve click is reserved for three categories: novel auth / session paths, infra / prod-affecting merges, and risk-flagged merges. See the `sdlc` skill — "uat→main merge-gate policy" — for the full rule, the category list, and the "when uncertain" escalation path.
|
||||||
|
|
||||||
## When uncertain
|
## When uncertain
|
||||||
|
|
||||||
If a code-quality call isn't covered above and you can't decide cleanly, escalate to the CTO via comment rather than guessing.
|
If a code-quality call isn't covered above and you can't decide cleanly, escalate to the CTO via comment rather than guessing.
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
name: devops
|
||||||
|
description: >
|
||||||
|
Infrastructure lifecycle for GroomBook. Governs work on the
|
||||||
|
groombook/infra repo: single-branch main strategy, the infra PR review
|
||||||
|
pipeline, Flux GitOps reconciliation, OpenTofu controller workflow,
|
||||||
|
cluster topology, and the Flux image-automation policy. For application
|
||||||
|
code, see the sdlc skill.
|
||||||
|
---
|
||||||
|
|
||||||
|
# DevOps Practices
|
||||||
|
|
||||||
|
This skill governs work on **`groombook/infra`**. For application code lifecycle, see the `sdlc` skill. For PR/test discipline and the `cc @cpfarhood` visibility rule, see `coding-standards`. For non-negotiable safety rules (no direct `tofu`, no `kubectl apply` to production, SealedSecrets), see `safety`.
|
||||||
|
|
||||||
|
## Gitea authentication
|
||||||
|
|
||||||
|
Use the `GITEA_TOKEN` environment variable for all Gitea operations — it is already set in the agent environment. Use the **`tea`** CLI for all Gitea/Git operations (e.g., `tea issue list`, `tea pr create`). Gitea is the primary source of truth.
|
||||||
|
|
||||||
|
## Branch strategy
|
||||||
|
|
||||||
|
`groombook/infra` uses a single long-lived branch: **`main`**. Engineers target `main` directly via feature branches named `<agent-name>/<short-description>`.
|
||||||
|
|
||||||
|
## Pipeline
|
||||||
|
|
||||||
|
1. **Engineer** branches from `main`, writes code.
|
||||||
|
2. **Engineer** opens a PR against `main`.
|
||||||
|
3. **CI** fail → back to **Engineer**.
|
||||||
|
4. **CI** pass → **QA** performs code review.
|
||||||
|
5. **QA** rejected → back to **Engineer**.
|
||||||
|
6. **QA** approved → **CTO** performs code review.
|
||||||
|
7. **CTO** rejected → back to **Engineer**.
|
||||||
|
8. **CTO** approved → **Engineer** merges PR → **Flux** reconciles automatically.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tea pr create --base main --title "..." --body "... cc @cpfarhood"
|
||||||
|
```
|
||||||
|
|
||||||
|
Gitea branch protection requires CI checks to pass. See `coding-standards` for the no-self-merge contract and the `cc @cpfarhood` rule.
|
||||||
|
|
||||||
|
## Infrastructure topology
|
||||||
|
|
||||||
|
* **Production:** namespace `groombook`, FQDN `demo.groombook.dev`
|
||||||
|
* **UAT:** namespace `groombook-uat`, FQDN `uat.groombook.dev`
|
||||||
|
* **Dev:** namespace `groombook-dev`, FQDN `dev.groombook.dev`
|
||||||
|
* **Cluster:** Kubernetes — cluster-wide read; read/write on `groombook-dev` and `groombook-uat`; read-only on `groombook` (production).
|
||||||
|
* **Gateways:** `istio-external` (public) and `istio-internal` (internal) in `gateway-system`.
|
||||||
|
* **Container registry:** `git.farh.net/groombook/<service>` only.
|
||||||
|
|
||||||
|
## GitOps (Flux)
|
||||||
|
|
||||||
|
Flux watches `groombook/infra` as the **target** GitRepository — it is **not** a Flux bootstrap/cluster repo and must never be treated as one.
|
||||||
|
|
||||||
|
Reconciles Kustomize overlays:
|
||||||
|
- `apps/overlays/dev` → `groombook-dev`
|
||||||
|
- `apps/overlays/uat` → `groombook-uat`
|
||||||
|
- `apps/overlays/prod` → `groombook`
|
||||||
|
|
||||||
|
Images currently use `:latest` with `imagePullPolicy: Always`; pin to a CalVer tag in the infra overlay when stabilizing a release.
|
||||||
|
|
||||||
|
**Policy — Flux Image Tag Automation is DENIED.** Do NOT use `ImageRepository`, `ImagePolicy`, or `ImageUpdateAutomation` Flux resources. Image tag updates must be made intentionally via a PR to `groombook/infra` — typically as the final step of the `sdlc` application pipeline (Phase 5).
|
||||||
|
|
||||||
|
## Infrastructure as Code
|
||||||
|
|
||||||
|
Terraform (OpenTofu) is deployed via the **Flux OpenTofu Controller** in a GitOps fashion. Submit Terraform configurations via a PR to `groombook/infra` — the tofu controller reconciles them on merge. See `safety` for the prohibition on running `tofu` directly and on `kubectl apply` against production.
|
||||||
|
|
||||||
|
## Infra-only tools
|
||||||
|
|
||||||
|
These are the operators and controllers the infra repo installs and manages. Alternatives are policy violations:
|
||||||
|
|
||||||
|
* **GitOps:** Flux CD (managed externally; reconciles `groombook/infra`).
|
||||||
|
* **IaC:** Flux OpenTofu Controller.
|
||||||
|
* **Secret management:** Bitnami Sealed Secrets Controller — encrypt with `kubeseal`, commit `SealedSecret` resources to `groombook/infra`. No plain Kubernetes secrets.
|
||||||
|
* **Database operator:** CloudNativePG (Postgres).
|
||||||
|
* **Cache / pub-sub operator:** DragonflyDB.
|
||||||
|
|
||||||
|
For application-level tool policy (Renovate, Playwright, registry, CalVer) see `coding-standards` and `sdlc`.
|
||||||
+38
-1
@@ -22,10 +22,47 @@ The following rules apply to every GroomBook agent without exception.
|
|||||||
|
|
||||||
* **Never `kubectl create secret` in production.** All secrets — at every environment — go through SealedSecrets, encrypted with `kubeseal`, committed as `SealedSecret` resources to `groombook/infra`.
|
* **Never `kubectl create secret` in production.** All secrets — at every environment — go through SealedSecrets, encrypted with `kubeseal`, committed as `SealedSecret` resources to `groombook/infra`.
|
||||||
|
|
||||||
* **Never bypass the merge gate.** No self-merging PRs. No pushing directly to `dev`, `uat`, or `main`. Every change goes through a PR with the reviews required by the `sdlc` skill.
|
* **Never bypass the merge gate.** No pushing directly to `dev`, `uat`, or `main`. Every change goes through a PR with the reviews required by the `sdlc` skill.
|
||||||
|
|
||||||
* **Never run `tofu` directly.** Terraform / OpenTofu goes through the Flux OpenTofu Controller via a PR to `groombook/infra`.
|
* **Never run `tofu` directly.** Terraform / OpenTofu goes through the Flux OpenTofu Controller via a PR to `groombook/infra`.
|
||||||
|
|
||||||
|
* **Always read-before-write when updating `adapterConfig.env`.** The Paperclip `PATCH /api/agents/{agentId}` endpoint with an `adapterConfig.env` body **replaces the entire env object** — sending a partial payload silently drops every key you did not include. Before writing any env variable, read the current config first, merge your changes on top, and send the full merged object:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Read existing config
|
||||||
|
existing=$(curl -s "$PAPERCLIP_API_URL/api/agents/<agentId>" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY")
|
||||||
|
|
||||||
|
# 2. Merge: spread existing env, then apply new keys on top
|
||||||
|
curl -s -X PATCH "$PAPERCLIP_API_URL/api/agents/<agentId>" \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$(echo "$existing" | jq '.adapterConfig.env + {"NEW_KEY": {"type":"plain","value":"val"}} | {adapterConfig: {env: .}}')"
|
||||||
|
```
|
||||||
|
|
||||||
|
Skipping the read step is a destructive operation — it erases all existing env vars for that agent.
|
||||||
|
|
||||||
## If you are unsure
|
## If you are unsure
|
||||||
|
|
||||||
If you are unsure whether an action is safe, **stop**. Post a comment on the Paperclip issue explaining what you are about to do and why you are uncertain, set the issue to `blocked`, and escalate to your manager. Do not guess.
|
If you are unsure whether an action is safe, **stop**. Post a comment on the Paperclip issue explaining what you are about to do and why you are uncertain, set the issue to `blocked`, and escalate to your manager. Do not guess.
|
||||||
|
|
||||||
|
## Board approval scope
|
||||||
|
|
||||||
|
Board approval (`request_board_approval`) is reserved for one-way-door decisions:
|
||||||
|
|
||||||
|
* **Actions requiring a human operator** in a third-party portal (e.g. Gitea Owners team config, external vendor consoles).
|
||||||
|
* **Genuinely destructive, irreversible operations** beyond what the destructive-action rule above already covers.
|
||||||
|
* **Out-of-scope decisions** that exceed the agent's mandate.
|
||||||
|
* **New spend or resource authorizations.**
|
||||||
|
* **Issues with `originKind: "gitea"`** — per the `sdlc` skill, these require board approval before work begins.
|
||||||
|
|
||||||
|
Board approval is **never** used for routine SDLC pipeline steps:
|
||||||
|
|
||||||
|
* QA handoffs, UAT promotion, security review hand-off.
|
||||||
|
* Returning a failing PR to the engineer or CTO.
|
||||||
|
* Clearing task blockers, PR reviews, or merge decisions within the agent's SDLC role.
|
||||||
|
* Feature triage decisions (Accepted / Backlogged / Denied).
|
||||||
|
* Any standard dev → uat → prod progression.
|
||||||
|
|
||||||
|
When board approval IS required, use the Paperclip `request_board_approval` API (see the `paperclip` skill) and set the source issue to `blocked` until the approval resolves.
|
||||||
|
|||||||
+72
-68
@@ -1,45 +1,47 @@
|
|||||||
---
|
---
|
||||||
name: sdlc
|
name: sdlc
|
||||||
description: >
|
description: >
|
||||||
Software development lifecycle for GroomBook. Covers Gitea authentication,
|
Software development lifecycle for GroomBook application repos. Covers
|
||||||
branch strategy across Dev/UAT/Prod, the SDLC pipeline phases,
|
Gitea authentication, the 3-branch dev/uat/main strategy, the SDLC
|
||||||
PR review and merge policy, infrastructure layout, the Gitea-origin issue
|
pipeline phases 1-5, the uat→main merge-gate policy (engineer
|
||||||
board-approval gate, the cc-cpfarhood visibility rule,
|
self-merge when pre-gates are green; CTO Gitea Approve only for
|
||||||
and delegation model tier policy.
|
novel auth, infra/prod-affecting, and risk-flagged merges),
|
||||||
|
the Stage 1 CI image build, the authentication framework, and
|
||||||
|
application-tool policy. For infrastructure (groombook/infra), see
|
||||||
|
the devops skill.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Software Development Lifecycle
|
# Software Development Lifecycle
|
||||||
|
|
||||||
|
This skill governs **application code repos**. For infrastructure (`groombook/infra`), see the `devops` skill. For PR/test discipline and the `cc @cpfarhood` visibility rule, see `coding-standards`. For non-negotiable safety rules, see `safety`. The **uat→main merge-gate policy** (which uat→main PRs need a CTO Gitea Approve click vs. engineer self-merge) is defined in this skill — see "uat→main merge-gate policy" below.
|
||||||
|
|
||||||
## Gitea authentication
|
## Gitea authentication
|
||||||
|
|
||||||
**Use the `GITEA_TOKEN`** environment variable for all Gitea operations. It is already set in the agent environment. Use the **`tea`** CLI for all Gitea/Git operations (e.g., `tea issue list`, `tea pr create`). The token expires when the environment variable is rotated — re-invoke any Gitea operation if you get a 401.
|
**Use the `GITEA_TOKEN`** environment variable for all Gitea operations. It is already set in the agent environment. Use the **`tea`** CLI for all Gitea/Git operations (e.g., `tea issue list`, `tea pr create`). The token expires when the environment variable is rotated — re-invoke any Gitea operation if you get a 401.
|
||||||
|
|
||||||
Gitea is the **primary source of truth**. Every Paperclip issue must have a corresponding Gitea issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified.
|
Gitea is the **primary source of truth**. Every Paperclip issue must have a corresponding Gitea issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified.
|
||||||
|
|
||||||
|
|
||||||
## Branch strategy
|
## Branch strategy
|
||||||
|
|
||||||
Three long-lived branches map to the three deployment environments:
|
Three long-lived branches map to the three deployment environments:
|
||||||
|
|
||||||
| Branch | Environment | Who merges | Prerequisites for merge |
|
| Branch | Environment | Who merges | Prerequisites for merge |
|
||||||
|--------|-------------|-----------|-----------|
|
|--------|-------------|-----------|-----------|
|
||||||
| `dev` | Dev | Engineer | None (self-merges after CI passes) |
|
| `dev` | Dev | Engineer | CI passes |
|
||||||
| `uat` | UAT | Engineer | QA code review approval |
|
| `uat` | UAT | Engineer | QA code review approval |
|
||||||
| `main` | Production | Engineer | UAT validation & CTO code review |
|
| `main` | Production | Engineer | UAT validation, security review, and the uat→main merge-gate policy (below) |
|
||||||
|
|
||||||
**Engineers always target `dev` first** — never `uat` or `main` directly.
|
**Engineers always target `dev` first** — never `uat` or `main` directly.
|
||||||
- Feature branches: `<agent-name>/<short-description>`.
|
- Feature branches: `<agent-name>/<short-description>`.
|
||||||
|
|
||||||
## Pull requests
|
## Pull requests
|
||||||
|
|
||||||
All changes happen via pull request. Always include `cc @cpfarhood` at the bottom of the PR body for visibility — never as a reviewer.
|
All changes happen via pull request. Gitea branch protection requires CI checks to pass. See `coding-standards` for the no-self-merge contract and the `cc @cpfarhood` visibility rule.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tea pr create --base dev --title "..." --body "... cc @cpfarhood"
|
tea pr create --base dev --title "..." --body "... cc @cpfarhood"
|
||||||
```
|
```
|
||||||
|
|
||||||
Gitea branch protection requires CI checks to pass.
|
|
||||||
|
|
||||||
## SDLC pipeline
|
## SDLC pipeline
|
||||||
|
|
||||||
### Phase 1 — Dev
|
### Phase 1 — Dev
|
||||||
@@ -65,76 +67,78 @@ Gitea branch protection requires CI checks to pass.
|
|||||||
2. **UAT** fail → back to **Engineer** (return to Phase 1).
|
2. **UAT** fail → back to **Engineer** (return to Phase 1).
|
||||||
3. **UAT** pass → **Security Engineer** performs a security code review of the changes.
|
3. **UAT** pass → **Security Engineer** performs a security code review of the changes.
|
||||||
4. **Security** fail → back to **Engineer** (return to Phase 1).
|
4. **Security** fail → back to **Engineer** (return to Phase 1).
|
||||||
5. **Security** pass → **Engineer** opens a PR from `uat` to `main`.
|
5. **Security** pass → Begin Phase 4.
|
||||||
6. **CI** fail → back to **Engineer** (return to Phase 1).
|
|
||||||
7. **CI** pass → Begin Phase 4.
|
|
||||||
|
|
||||||
### Phase 4 — Production
|
### Phase 4 — Production Promotion
|
||||||
|
|
||||||
1. **CTO** performs code review.
|
1. **Engineer** opens a PR from `uat` to `main`.
|
||||||
2. **CTO** approved → **Engineer** merges PR.
|
2. **CI** fail → back to **Engineer** (return to Phase 1).
|
||||||
3. **CTO** rejected → back to **Engineer** (return to Phase 1).
|
3. **CI** pass → **Engineer** classifies the PR against the **uat→main merge-gate policy** (below):
|
||||||
4. **CI** deploys automatically to Production (`https://demo.groombook.dev`).
|
* **In a category that requires CTO Gitea Approve** (novel auth / session paths, infra / prod-affecting merges, `risk:cto-approve` label or explicit CTO/CEO sign-off request) → Engineer pings the CTO for a Gitea Approve click.
|
||||||
|
* **CTO** rejected → back to **Engineer** (return to Phase 1).
|
||||||
|
* **CTO** approved → continue to step 4.
|
||||||
|
* **Outside all three categories** → no CTO click needed; jump to step 4 once the four pre-gates (QA, UAT deploy, UAT regression, security) are green.
|
||||||
|
4. **Engineer** merges the PR.
|
||||||
|
5. **CI** fail → back to **Engineer** (return to Phase 1).
|
||||||
|
6. **CI** pass → Begin Phase 5.
|
||||||
|
|
||||||
## Infrastructure
|
### Phase 5 — Production Deployment
|
||||||
|
|
||||||
* **Production:** namespace `groombook`, FQDN `demo.groombook.dev`
|
The **Engineer** opens a PR against `groombook/infra` to update the relevant Kustomize overlay with the new image tag. From this point the work follows the **`devops` skill pipeline** end-to-end — review, merge, and Flux reconciliation are all owned there. On merge, Flux rolls out the updated pods to production (`https://demo.groombook.dev`).
|
||||||
* **UAT:** namespace `groombook-uat`, FQDN `uat.groombook.dev`
|
|
||||||
* **Dev:** namespace `groombook-dev`, FQDN `dev.groombook.dev`
|
## uat→main merge-gate policy
|
||||||
* **Cluster:** Kubernetes — cluster-wide read; read/write on `groombook-dev` and `groombook-uat`; read-only on `groombook` (production).
|
|
||||||
* **Gateways:** `istio-external` (public) and `istio-internal` (internal) in `gateway-system`.
|
This is the process policy that governs which `uat → main` PRs need a CTO Gitea Approve click vs. engineer self-merge. It exists because the Gitea `required_approvals` branch-protection gate is satisfied only by a Gitea Approve click — the Paperclip issue-thread QA/UAT-deploy/UAT-regression/security approvals do **not** clear it. The engineer **MUST** classify every `uat → main` PR against this policy before merging.
|
||||||
* **Container registry:** `git.farh.net/groombook/<service>` only.
|
|
||||||
|
### The four pre-gates are unchanged
|
||||||
|
|
||||||
|
A `uat → main` PR is mergeable only when all of these are green on the linked Paperclip issue: QA code review, UAT deploy, UAT regression, and security review. The CTO Gitea Approve click is **in addition to** those four when the PR falls in one of the categories below; it does not replace any of them.
|
||||||
|
|
||||||
|
### Categories that require CTO Gitea Approve
|
||||||
|
|
||||||
|
A CTO Gitea Approve click is required only for PRs in one of the following three categories:
|
||||||
|
|
||||||
|
1. **Novel auth / session paths.** Login, OIDC, OOBE, session middleware, token issuance, password reset, MFA, or any new auth provider integration. Routine changes to auth-gated UI (button styling, error messages, form layout, copy edits) are **not** in this category.
|
||||||
|
2. **Infra / prod-affecting merges.** Deploys, infra manifests, secrets, GitOps overlays, CI/CD, `main` branch protection, prod-affecting routing/ingress, or any change that mutates prod state. **All Phase 5 infra overlay PRs in `groombook/infra` require CTO Gitea Approve without exception.**
|
||||||
|
3. **Risk-flagged merges.** The PR carries the `risk:cto-approve` label, **or** the PR or its linked Paperclip issue thread contains an explicit CTO/CEO sign-off request.
|
||||||
|
|
||||||
|
### Engineer workflow
|
||||||
|
|
||||||
|
The engineer who opened the PR classifies it against the three categories above (escalating to the CTO via comment if the call is unclear), then:
|
||||||
|
|
||||||
|
* **In a category** → request a CTO Gitea Approve click. Engineer merges once the CTO has approved.
|
||||||
|
* **Outside all three categories** → no CTO click needed. Engineer merges once the four pre-gates are green.
|
||||||
|
|
||||||
|
**Board/CEO approval is via SDLC code review (judgment) on the Paperclip issue, not via a Gitea Approve click.** The CEO's role at Phase 4 is to perform the code review on the Paperclip issue thread; that approval satisfies the "CEO approved" pre-condition and is recorded in Paperclip, not in Gitea.
|
||||||
|
|
||||||
|
### When uncertain
|
||||||
|
|
||||||
|
If a `uat → main` PR does not obviously belong to a category, comment on the PR with `@<the-dogfather>` (or escalate to the CEO if the CTO is unavailable) and pause the merge. Do not guess the category — a routine PR is a routine PR, but a borderline PR is cheaper to escalate than to misclassify.
|
||||||
|
|
||||||
|
## Stage 1 CI — Image build
|
||||||
|
|
||||||
|
Triggered automatically on every merge to `main` in an application repo:
|
||||||
|
- Builds and tags the Docker image: CalVer (`YYYY.MM.DD[.N]`), `latest`, and `sha-<hash>`
|
||||||
|
- Pushes tagged images to `git.farh.net/groombook/<service>` (see `coding-standards` for the registry and CalVer policy)
|
||||||
|
- Creates a CalVer git tag in the source repo
|
||||||
|
|
||||||
|
Stage 2 (Flux GitOps deployment) is owned by `devops`.
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
* **Framework:** Better-Auth.
|
* **Framework:** Better-Auth.
|
||||||
* **OAuth Providers:** GroomBook (Authentik), Google and Apple.
|
* **OAuth Providers:** GroomBook (Authentik), Google, and Apple.
|
||||||
* **SSO:** Authentik OIDC at `https://auth.farh.net` (credentials in `authentik-credentials` secret).
|
* **SSO:** Authentik OIDC at `https://auth.farh.net` (credentials in `authentik-credentials` secret).
|
||||||
* **Never build custom authentication.**
|
* **Never build custom authentication.**
|
||||||
|
|
||||||
## Deployment — 2-stage Flux GitOps
|
## Application tools (canonical, not alternatives)
|
||||||
|
|
||||||
**Stage 1 — CI (runs in each application repo):**
|
These are application-level dependency choices. Alternatives are policy violations:
|
||||||
- Triggered automatically on every merge to `main`
|
|
||||||
- Builds and tags the Docker image: CalVer (`YYYY.MM.DD[.N]`), `latest`, and `sha-<hash>`
|
|
||||||
- Pushes tagged images to `git.farh.net/groombook/<service>`
|
|
||||||
- Creates a CalVer git tag in the source repo
|
|
||||||
|
|
||||||
**Stage 2 — GitOps (Flux, managed externally):**
|
* **Database:** CloudNativePG-managed Postgres — no SQLite, MariaDB, or MySQL.
|
||||||
- Flux watches `groombook/infra` as the **target** GitRepository — it is **not** a Flux bootstrap/cluster repo and must never be treated as one.
|
* **Cache / pub-sub:** DragonflyDB — no Redis.
|
||||||
- Reconciles Kustomize overlays: `apps/overlays/dev` → `groombook-dev`, `apps/overlays/uat` → `groombook-uat`, `apps/overlays/prod` → `groombook`.
|
* **Authentication:** Better-Auth + Google + Apple + Authentik (see Authentication above).
|
||||||
- Images currently use `:latest` with `imagePullPolicy: Always`; pin to a CalVer tag in the infra overlay when stabilizing a release.
|
|
||||||
|
|
||||||
**Policy — Flux Image Tag Automation is DENIED.** Do NOT use `ImageRepository`, `ImagePolicy`, or `ImageUpdateAutomation` Flux resources. Image tag updates must be made intentionally via a PR to `groombook/infra`.
|
|
||||||
|
|
||||||
**To deploy a change:**
|
|
||||||
1. Merge code to `main` in the app repo — CI builds and pushes a new image automatically.
|
|
||||||
2. Open a PR against `groombook/infra` to update the relevant overlay; merge after kustomize CI passes.
|
|
||||||
3. Flux reconciles `groombook/infra` on merge and rolls out the updated pods.
|
|
||||||
|
|
||||||
**To force a rollout without a manifest change:**
|
|
||||||
```bash
|
|
||||||
kubectl rollout restart deployment/<name> -n <namespace>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Infrastructure as Code
|
|
||||||
|
|
||||||
Terraform (OpenTofu) is deployed via the **Flux OpenTofu Controller** in a GitOps fashion. Submit Terraform configurations via a PR to `groombook/infra` — the tofu controller reconciles them on merge.
|
|
||||||
|
|
||||||
**Never run `tofu` directly.** Never `kubectl apply` against production. Production changes go through Flux only. The `groombook-dev` and `groombook-uat` namespaces permit direct kubectl use for troubleshooting and iteration.
|
|
||||||
|
|
||||||
## Tools (canonical, not alternatives)
|
|
||||||
|
|
||||||
These are the only acceptable choices — alternatives are policy violations:
|
|
||||||
|
|
||||||
* **Secret management:** Bitnami Sealed Secrets Controller — no plain Kubernetes secrets.
|
|
||||||
* **Database:** CloudNativePG Operator (Postgres) — no SQLite, MariaDB, or MySQL.
|
|
||||||
* **Cache / pub-sub:** DragonflyDB Operator — no Redis.
|
|
||||||
* **Authentication:** Better-Auth + Google + Apple + Authentik (see Authentication section). Never build custom auth.
|
|
||||||
* **Dependency updates:** Mend Renovate. **Dependabot is not used and will not be used.** Do not configure it.
|
* **Dependency updates:** Mend Renovate. **Dependabot is not used and will not be used.** Do not configure it.
|
||||||
* **Container registry:** `git.farh.net/groombook/<service>` — no Docker Hub for first-party images.
|
|
||||||
* **Browser automation:** the `playwright` MCP server (`http://playwright:8931/mcp`). Target dev only — never test production.
|
* **Browser automation:** the `playwright` MCP server (`http://playwright:8931/mcp`). Target dev only — never test production.
|
||||||
|
|
||||||
## External communication
|
For the container registry, CalVer versioning, and general PR/test discipline, see `coding-standards`. For the operator install side (CNPG, Dragonfly, Sealed Secrets), see `devops`.
|
||||||
|
|
||||||
When communicating in any context visible outside the GroomBook agent team (external users, human reviewers, non-agent entities), include `cc @cpfarhood` for visibility — never as a reviewer.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user