31 Commits

Author SHA1 Message Date
Flea Flicker 5d39685451 docs(sdlc): move uat→main merge-gate policy here; CTO Approve only for novel auth, infra/prod, and risk-flagged (GRO-2377) (#13)
Co-authored-by: Flea Flicker <flea@groombook.dev>
Co-committed-by: Flea Flicker <flea@groombook.dev>
2026-06-12 16:27:24 +00:00
Chris Farhood 36310c48db refactor(skills): resolve self-merge contradiction with sdlc
- coding-standards: replace "no agent merges their own PR" with the
  reviews-required-then-engineer-may-merge rule consistent with sdlc
- safety: drop stale "No self-merging PRs" line from the merge-gate
  rule for the same reason

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 09:26:05 -04:00
Chris Farhood 738f5d8f05 Merge pull request 'feat(safety): require read-before-write for adapterConfig.env updates' (#12) from fix/gro-2049-adapter-env-preservation into main
Reviewed-on: #12
2026-06-02 01:07:28 +00:00
Flea Flicker cffa73cd97 feat(safety): require read-before-write for adapterConfig.env updates
Sending a partial adapterConfig.env payload silently drops all keys not
included, which is what caused Shedward's env vars to be erased when UAT
passwords were added (GRO-2049). Adds an explicit non-negotiable rule with
the safe read-merge-write pattern to prevent recurrence.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-02 01:05:49 +00:00
Scrubs McBarkley cd5d9c5614 feat(safety): add board approval scope section
CTO content-verified + QA (Lint Roller) officially approved. Merged by CEO (Scrubs McBarkley) as non-self merge on markdown-only org repo. GRO-1838.
2026-05-28 18:45:26 +00:00
The Dogfather 6e0e29f374 feat(safety): add board approval scope section 2026-05-28 12:17:23 +00:00
The Dogfather f69319e270 Revert "feat(safety): add board approval scope section" (direct push - will redo via PR) 2026-05-28 12:14:29 +00:00
The Dogfather deb507714b feat(safety): add board approval scope section 2026-05-28 12:13:27 +00:00
Flea Flicker 40f8153c86 feat(safety): add board approval scope section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 12:05:46 +00:00
Chris Farhood 4df9637518 Merge pull request 'Split devops and sdlc skills by scope; dedupe shared content' (#9) from claude/devops-sdlc-split into main
Reviewed-on: #9
2026-05-28 01:18:55 +00:00
Chris Farhood 11fd2a4c34 Collapse sdlc Phase 5 to a redirect into the devops pipeline
Phase 5 is an infra PR against groombook/infra, which means it is governed
by the devops pipeline. Spelling out a separate (QA-only) review flow here
both duplicates devops and contradicted its QA+CTO requirement. Replaced
the step list with a one-paragraph hand-off.

Resolves the policy ambiguity flagged in the PR description.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 21:16:10 -04:00
Chris Farhood d6b13fa58d Split devops and sdlc skills by scope; dedupe shared content
devops/SKILL.md is now the canonical home for infrastructure lifecycle
(groombook/infra, single-branch main, Flux + OpenTofu controller, cluster
topology). sdlc/SKILL.md is scoped to application code (3-branch dev/uat/main,
Phases 1-5, Stage 1 CI image build, app-tool policy). Each skill cross-refs
the other and defers to coding-standards/safety for cross-cutting rules
rather than restating them.

Fixes in devops/SKILL.md:
- Rewrote frontmatter description (was a copy of sdlc, referenced phases
  and dev/uat/prod that do not apply).
- Hoisted "applies to groombook/infra" to a top-level scope statement.
- Renumbered the pipeline (was 1,2,3,4,4,5,4,5,5) and fixed --base dev
  -> --base main in the tea example.
- Closed an unterminated bold marker.
- Removed Authentication framework, Stage 1 image build, and the
  "never tofu / never kubectl apply" lines (now cited from sdlc / safety).
- Trimmed the tools list to infra-only operators and controllers.

Trims in sdlc/SKILL.md:
- Removed Infrastructure topology, IaC, Stage 2 GitOps detail, the Flux
  Image Automation DENIED policy, the "never tofu / never kubectl apply"
  lines, and the External communication section (cited from devops /
  safety / coding-standards instead).
- Trimmed the tools list to application-level dependency choices.
- Added a pointer from Phase 5 into the devops pipeline.

cc @cpfarhood

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:31:54 -04:00
Chris Farhood c756b16c7c more updates 2026-05-26 23:27:03 -04:00
Chris Farhood 743e913126 Update skills/sdlc/SKILL.md 2026-05-27 03:05:30 +00:00
Chris Farhood a0ae03e959 Update skills/sdlc/SKILL.md 2026-05-27 03:04:25 +00:00
Chris Farhood 643d9e8956 Update skills/sdlc/SKILL.md 2026-05-27 03:04:09 +00:00
Chris Farhood 93927ea402 Merge pull request 'udpate sdlc' (#8) from sdlc-updates into main
Reviewed-on: #8
2026-05-27 03:03:37 +00:00
Chris Farhood a51b28a315 minor tweaks 2026-05-26 23:03:17 -04:00
Chris Farhood 198ed88350 udpate sdlc 2026-05-26 23:01:12 -04:00
Chris Farhood 2ae9c4c2d4 Merge pull request 'chore(sdlc): align SDLC skill with cartsnitch/org structure' (#7) from loose-sdlc-to-match-privesc into main
Reviewed-on: #7
2026-05-26 15:32:24 +00:00
Chris Farhood c8d8cf562c chore: switch container registry references from ghcr.io to git.farh.net
GroomBook images live on the Gitea registry, not GitHub. Update SDLC,
coding-standards, and CLAUDE.md to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 09:45:20 -04:00
Chris Farhood 693f719332 Merge origin/main, discarding Scrubs's SDLC fix commit
Keep this branch's SDLC content (cartsnitch-aligned structure). Drop
adff13f's changes — registry should remain ghcr.io, engineer self-merges
to dev, and tool-deviation policy stays at board approval.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 09:43:25 -04:00
Chris Farhood bf5ecdc4dc chore(sdlc): align SDLC skill with cartsnitch/org structure
- CTO merges dev→uat (was QA); CEO Scrubs McBarkley merges uat→main (was Shedward)
- Simplify Gitea auth — GITEA_TOKEN is pre-set, drop tea login add
- Restore delegation model tier section
- Add Playwright MCP to canonical tools, CalVer tag detail, imagePullPolicy note
- Trim redundant UUIDs and the verbose pen-testing footnote

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 09:20:06 -04:00
Scrubs McBarkley adff13f0d1 fix: correct SDLC skill — merge policy, container registry, board approval
Fixes multiple systemic issues causing excessive board approval requests:
- Fix merge policy: CTO merges dev+uat, CEO merges main (not engineer/QA/UAT)
- Fix container registry: ghcr.io → git.farh.net (moved off GitHub)
- Remove invalid "deviate from tools → board approval" trigger; escalate to CTO instead
- Remove duplicate "engineer self-merges" step from Phase 1
- Fix Phase 4 production merge: Barkley assigns to CEO, CEO merges

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-26 11:08:25 +00:00
Chris Farhood a5e8027293 Merge pull request 'Add agent avatar images for GroomBook team' (#6) from loose-sdlc-to-match-privesc into main
Reviewed-on: #6
2026-05-25 21:21:31 +00:00
Chris Farhood 2d9e7cf8d1 Add agent avatar images for GroomBook team
Generated cartoon avatars for all 7 GroomBook agents:
- Scrubs McBarkley (CEO)
- Pawla Abdul (CMO)
- The Dogfather (CTO)
- Barkley Trimsworth (Security)
- Flea Flicker (Engineer)
- Lint Roller (QA)
- Shedward Scissorhands (UAT)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 17:19:37 -04:00
Chris Farhood 712133590c Merge pull request 'chore: loosen SDLC to match Privileged Escalation pattern' (#5) from loose-sdlc-to-match-privesc into main
Reviewed-on: #5
2026-05-24 19:35:25 +00:00
Chris Farhood 60b9b41d4b chore: loosen SDLC to match Privileged Escalation pattern
- Engineer self-merges to dev after CI passes
- QA merges dev→uat (not CTO)
- UAT merges uat→main (not CEO)
- Remove Phase 0 product intake, delegation model, handoff protocol
- Remove explicit no-self-merge rule (covered by pipeline gates)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:33:56 -04:00
Chris Farhood 403311044b Add .mcp.json 2026-05-24 18:15:50 +00:00
Chris Farhood 9f9fb356f4 Add CLAUDE.md and add agent UUIDs to SDLC skill
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 15:30:15 -04:00
The Dogfather 9cd8f1589f Merge pull request 'chore: migrate SDLC skill from GitHub to Gitea' (#4) from scrubs/gitea-migration-skills into main
chore: migrate SDLC skill from GitHub to Gitea (#4)

Replaces all GitHub references with Gitea equivalents in skills/sdlc/SKILL.md:
- Auth: github-app-token → tea CLI + GITEA_TOKEN
- Origin: github → gitea
- PR command: gh → tea
- CI: GitHub Actions → Gitea Actions
2026-05-19 23:17:33 +00:00
13 changed files with 242 additions and 171 deletions
+11
View File
@@ -0,0 +1,11 @@
{
"mcpServers": {
"gitea": {
"type": "http",
"url": "https://git-mcp.farh.net/mcp",
"headers": {
"Authorization": "Bearer ${GITEA_TOKEN}"
}
}
}
}
+27
View File
@@ -0,0 +1,27 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Purpose
This is the GroomBook **agent skills repository** — it contains skill definitions that govern how AI agents operate within the GroomBook organization. The `skills/` directory holds three skill files: `coding-standards`, `safety`, and `sdlc`.
## Skills Overview
- **coding-standards** — Engineering quality bar: priority (correctness > clarity > maintainability > performance > elegance), PR discipline, test requirements, no-hardcoded-values rules, CalVer versioning, `git.farh.net` container registry policy.
- **safety** — Non-negotiable rules: no plaintext secrets (use SealedSecrets), no `kubectl apply` to production (`groombook` namespace), no self-merging, no direct `tofu` runs, board approval for destructive actions, escalation protocol.
- **sdlc** — Full development lifecycle: Gitea authentication via `tea` CLI, branch strategy (`dev`/`uat`/`main`), SDLC pipeline phases, delegation model, handoff protocol (explicit PATCH assignment + status=todo + release checkout), infrastructure layout, and canonical tools list.
## Critical Operational Rules
- All changes go through PRs targeting `dev`. Never push directly to `dev`, `uat`, or `main`.
- No agent merges their own PR.
- Always include `cc @cpfarhood` at the bottom of PR bodies.
- Gitea-origin issues require board approval before work begins.
- Kubernetes secrets go through Bitnami Sealed Secrets — never commit plaintext secrets.
- Production (`groombook` namespace) is Flux-managed; never `kubectl apply` directly.
- Infrastructure changes go through Flux OpenTofu Controller via PR to `groombook/infra`.
## No Build/Test Commands
This repository contains only markdown skill files. There are no build, lint, or test commands — it is not an application codebase.
Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

+9 -4
View File
@@ -3,8 +3,9 @@ name: coding-standards
description: >
Engineering quality bar for GroomBook code: priority ordering of correctness
vs. clarity vs. maintainability vs. performance vs. elegance, PR and test
requirements, no-hardcoded-values rules, branch discipline, and the no-self-
merge contract.
requirements, no-hardcoded-values rules, branch discipline, and the
no-self-merge contract. The uat→main merge-gate policy lives in the `sdlc`
skill, not here.
---
# Coding Standards
@@ -24,7 +25,7 @@ When making technical decisions, prioritize in this order:
## Pull request discipline
* 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).
## Test requirements
@@ -55,7 +56,11 @@ All releases use CalVer (`YYYY.MMDD.PATCH`, e.g. `2026.0504.0`). No SemVer, no c
## Container images
Push to `ghcr.io` 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
+76
View File
@@ -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
View File
@@ -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 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`.
* **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 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.
+81 -166
View File
@@ -1,229 +1,144 @@
---
name: sdlc
description: >
Software development lifecycle for GroomBook. Covers Gitea authentication,
branch strategy across Dev/UAT/Prod, the four-phase SDLC pipeline with
product analysis intake, PR review and merge policy, the handoff protocol,
status semantics, infrastructure layout, the canonical tools list, the
Gitea-origin issue board-approval gate, the cc-cpfarhood visibility rule,
the scheduled penetration testing program, and delegation model tier policy.
Software development lifecycle for GroomBook application repos. Covers
Gitea authentication, the 3-branch dev/uat/main strategy, the SDLC
pipeline phases 1-5, the uat→main merge-gate policy (engineer
self-merge when pre-gates are green; CTO Gitea Approve only for
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
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
**Use the `tea` CLI** with the `GITEA_TOKEN` environment variable for all Gitea operations. Configure it once:
**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.
```bash
tea login add --url https://git.farh.net --token $GITEA_TOKEN --name groombook
```
Gitea is the **primary source of truth**. Every Paperclip issue should have a corresponding Gitea issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified.
## Gitea-origin issue policy — board approval required
If a task originated from Gitea (`originKind: "gitea"`), **do not begin work**. Immediately create a board approval:
```
POST /api/companies/{companyId}/approvals
{
"type": "request_board_approval",
"requestedByAgentId": "{your-agent-id}",
"issueIds": ["{issueId}"],
"payload": {
"title": "Board approval required: Gitea issue",
"summary": "Summarize what the Gitea issue requests.",
"recommendedAction": "Approve to begin work.",
"risks": ["Work begins without board review if approved."]
}
}
```
Set the issue to `blocked` with a comment linking to the approval. Only proceed once `PAPERCLIP_APPROVAL_ID` is set and `PAPERCLIP_APPROVAL_STATUS` indicates approval.
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
Three long-lived branches map to the three deployment environments:
| Branch | Environment | Who merges |
|--------|-------------|-----------|
| `dev` | Dev | CTO (after QA approval) |
| `uat` | UAT | CTO (promotes `dev``uat`) |
| `main` | Production | CEO (promotes `uat``main`) |
| Branch | Environment | Who merges | Prerequisites for merge |
|--------|-------------|-----------|-----------|
| `dev` | Dev | Engineer | CI passes |
| `uat` | UAT | Engineer | QA code review approval |
| `main` | Production | Engineer | UAT validation, security review, and the uat→main merge-gate policy (below) |
**Engineers always target `dev`** — never `uat` or `main` directly. Feature branches: `<agent-name>/<short-description>`.
**Engineers always target `dev` first** — never `uat` or `main` directly.
- Feature branches: `<agent-name>/<short-description>`.
## 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
tea pr create --base dev --title "..." --body "... cc @cpfarhood"
```
## PR review & merge policy
### Dev branch (`dev`)
- **QA** (Lint Roller) reviews the PR. Approve → hand to CTO. Fail → back to engineer directly with exact details.
- **CTO** (The Dogfather) reviews. Approve → CTO merges the `dev` PR. Fail → back to engineer.
### UAT branch (`uat`)
- **CTO** opens and merges a `dev``uat` PR.
### Main branch (`main`)
- **CEO** (Scrubs McBarkley) reviews and merges the `uat``main` PR.
`@cpfarhood` is cc'd for visibility on all PRs — never as a reviewer.
## SDLC pipeline
### Phase 0 — Product analysis (feature intake)
* Feature requests arrive at the CEO via Paperclip or Gitea Issues.
* CEO delegates to CMPO (Pawla Abdul) for review.
* CMPO returns one of three decisions:
* **Accepted** → CEO routes to CTO for work breakdown.
* **Backlogged** → CEO handles prioritization.
* **Denied** → CEO closes as unplanned.
* CTO breaks accepted work into atomic tasks and assigns to Engineering.
### Phase 1 — Dev
1. **Engineer** (Flea Flicker) branches from `dev`, writes code. GitOps deploys to dev on demand.
2. **Engineer** opens a PR against `dev`. CI must pass.
3. **QA (Lint Roller)** reviews the PR. Fail → back to engineer.
4. QA approves and hands off to CTO.
5. **CTO (The Dogfather)** reviews the PR. Fail → back to engineer.
6. **CTO** merges the dev PR.
7. **CI** builds and deploys automatically to Dev (`https://dev.groombook.dev`).
1. **Engineer** branches from `dev`, writes code.
2. **Engineer** opens a PR against `dev`.
3. **CI** fail → back to **Engineer**.
4. **CI** pass → **Engineer** merges PR.
5. **CI** builds and deploys automatically to Dev (`https://dev.groombook.dev`).
### Phase 2 — UAT promotion
8. **CTO** opens and merges a PR from `dev` to `uat`.
9. **CI** builds and deploys automatically to UAT (`https://uat.groombook.dev`).
10. **CTO** creates a UAT regression task for **Shedward Scissorhands** immediately after promoting.
1. **Engineer** opens a PR from `dev` to `uat`.
2. **CI** fail → back to **Engineer** (return to Phase 1).
3. **CI** pass → **QA** performs code review.
4. **QA** rejected → back to **Engineer** (return to Phase 1).
5. **QA** approved → **Engineer** merges PR.
6. **CI** builds and deploys automatically to UAT (`https://uat.groombook.dev`).
### Phase 3 — UAT testing & security
### Phase 3 — User Testing & Security Review
11. **UAT (Shedward Scissorhands)** runs full regression against UAT — every feature, no exceptions.
12. UAT fail → CTO redistributes to engineer (return to Phase 1).
13. UAT pass → **Security Engineer (Barkley Trimsworth)** performs a security code review of the changes.
14. Security fail → CTO redistributes to engineer (return to Phase 1).
1. **UAT (Shedward Scissorhands)** runs full regression against UAT — every feature, old and new, no exceptions.
2. **UAT** fail → back to **Engineer** (return to Phase 1).
3. **UAT** pass → **Security Engineer** performs a security code review of the changes.
4. **Security** fail → back to **Engineer** (return to Phase 1).
5. **Security** pass → Begin Phase 4.
### Phase 4 — Production
### Phase 4 — Production Promotion
15. Security pass → **CEO (Scrubs McBarkley)** reviews and merges the production PR (`uat → main`). Fail → back to CTO.
16. **CI** deploys automatically to Production (`https://demo.groombook.dev`).
1. **Engineer** opens a PR from `uat` to `main`.
2. **CI** fail → back to **Engineer** (return to Phase 1).
3. **CI** pass → **Engineer** classifies the PR against the **uat→main merge-gate policy** (below):
* **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.
### Hierarchy rules
### Phase 5 — Production Deployment
* CTO rejections at Dev go directly to the engineer (not back through QA).
* UAT failures (Shedward) go to CTO — CTO cascades to engineer.
* Security failures (Barkley) go to CTO — CTO cascades to engineer.
* CEO rejections at Prod go to CTO.
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`).
> **Penetration testing.** Barkley performs scheduled penetration testing against Production (`demo.groombook.dev`) and Demo independently of the PR workflow. Board-authorized; not triggered per-PR. Findings get filed as Paperclip issues with severity (`CRITICAL` / `HIGH` / `MEDIUM` / `LOW`) and routed to CTO for engineer redistribution.
## uat→main merge-gate policy
## Delegation model tier
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.
When creating subtasks for other agents, set `modelProfile: "cheap"` only for:
- Mechanical refactors or repetitive operations
- Basic information lookups
- Well-specified, bounded updates
### The four pre-gates are unchanged
Leave `modelProfile` unset for anything requiring judgment, reasoning, or QA review.
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.
When in doubt, leave it unset.
### Categories that require CTO Gitea Approve
## Handoff protocol — mandatory
A CTO Gitea Approve click is required only for PRs in one of the following three categories:
Every handoff to another agent requires ALL THREE steps:
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.
### 1. Explicit assignment
### Engineer workflow
`PATCH /api/issues/{id}` with `assigneeAgentId: "<target-agent-uuid>"`. Mentioning is NOT a handoff — the agent won't wake without explicit assignment.
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:
### 2. Status = `todo`
* **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.
Every handoff sets `status: "todo"`. Never `in_review`, never `backlog` — both are invisible in inbox-lite and the receiver won't wake.
**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.
### 3. Release checkout
### When uncertain
```
POST /api/issues/{issueId}/release
Headers: Authorization: Bearer $PAPERCLIP_API_KEY, X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID
```
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.
Without this release, the receiving agent cannot check out the issue.
## Stage 1 CI — Image build
**Saying you are reassigning a task is NOT the same as reassigning it.** Verify the PATCH succeeded (200) before posting a comment claiming the handoff is done.
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
## Infrastructure
* **Production / Demo:** 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` (publicly accessible) and `istio-internal` (internal only) in `gateway-system`.
* **Container registry:** `ghcr.io/groombook/<service>` only.
Stage 2 (Flux GitOps deployment) is owned by `devops`.
## Authentication
* **Framework:** Better-Auth.
* **Social login:** Google and Apple OAuth.
* **OAuth Providers:** GroomBook (Authentik), Google, and Apple.
* **SSO:** Authentik OIDC at `https://auth.farh.net` (credentials in `authentik-credentials` secret).
* **Never build custom authentication.**
## Deployment — 2-stage Flux GitOps
## Application tools (canonical, not alternatives)
**Stage 1 — CI (Gitea Actions, uses GitHub Actions-compatible YAML syntax, runs in each application repo):**
- Triggered automatically on every merge to `main`
- Builds and tags the Docker image
- Pushes tagged images to `ghcr.io/groombook/<service>`
These are application-level dependency choices. Alternatives are policy violations:
**Stage 2 — GitOps (Flux, managed externally):**
- Flux watches `groombook/infra` as the **target** GitRepository — it is **not** a Flux bootstrap/cluster repo.
- Reconciles Kustomize overlays: `apps/overlays/dev``groombook-dev`, `apps/overlays/uat``groombook-uat`, `apps/overlays/prod``groombook`.
* **Database:** CloudNativePG-managed Postgres — no SQLite, MariaDB, or MySQL.
* **Cache / pub-sub:** DragonflyDB — no Redis.
* **Authentication:** Better-Auth + Google + Apple + Authentik (see Authentication above).
* **Dependency updates:** Mend Renovate. **Dependabot is not used and will not be used.** Do not configure it.
* **Browser automation:** the `playwright` MCP server (`http://playwright:8931/mcp`). Target dev only — never test production.
**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** (pick up new `:latest` on stuck pods):
```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 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.
## 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.**
* **Container registry:** `ghcr.io/groombook/<service>` — no Docker Hub for first-party images.
If a task requires deviating from any of the above, treat it as a destructive action: stop, file an issue with rationale, request board approval.
## External communication
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.
## No self-merge
No agent merges their own PR. The merger is always the next role up the SDLC ladder (CTO for `dev` and `uat`, CEO for `main`).
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`.