From 1d817d3e2de2ee45d4ea2cdf7f11df27d88be5a1 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Sun, 3 May 2026 19:10:42 -0400 Subject: [PATCH] feat(skills): add sdlc, safety, and coding-standards org skills Mirrors the groombook/org and privilegedescalation/org pattern: extract company-wide policy that's currently inlined across each agent's AGENTS.md (plus auxiliary HEARTBEAT.md / GITHUB.md / SOUL.md / TOOLS.md / INFRASTRUCTURE.md files) into three shared skills. Agents will reference these via one-line invocation reminders in their Wake additions section once the AGENTS.md files are rewritten. --- skills/coding-standards/SKILL.md | 93 +++++++++++++++ skills/safety/SKILL.md | 46 ++++++++ skills/sdlc/SKILL.md | 192 +++++++++++++++++++++++++++++++ 3 files changed, 331 insertions(+) create mode 100644 skills/coding-standards/SKILL.md create mode 100644 skills/safety/SKILL.md create mode 100644 skills/sdlc/SKILL.md diff --git a/skills/coding-standards/SKILL.md b/skills/coding-standards/SKILL.md new file mode 100644 index 0000000..f7f0a32 --- /dev/null +++ b/skills/coding-standards/SKILL.md @@ -0,0 +1,93 @@ +--- +name: coding-standards +description: > + Engineering quality bar for CartSnitch code: priority ordering of correctness + vs. clarity vs. maintainability vs. performance vs. elegance, PR and test + requirements, no-hardcoded-values rules, branch discipline, the + no-self-merge contract, and task-decomposition standards for delegation. +--- + +# Coding Standards + +These rules apply to any CartSnitch agent that writes, reviews, or merges code. + +## Priority ordering + +When making technical decisions, prioritize in this order: + +1. **Correctness** — does it work? Does it handle edge cases? Have you proven it, not assumed it? +2. **Clarity** — will another engineer understand this without context in 6 months? +3. **Maintainability** — will it be safe to change? +4. **Performance** — fast enough for the use case? Profile before optimizing. +5. **Elegance** — nice if free; never trade any of the above for it. + +## Pull request discipline + +* All changes go through a PR. **Never push directly to `dev`, `uat`, or `main`.** +* No agent merges their own PR. +* Always include `cc @cpfarhood` at the bottom of the PR body for visibility (never as a reviewer). +* Engineers always target `dev` — never `uat` or `main` directly. + +## Test requirements + +* **Every PR must include tests** for new code paths. No exceptions for "small" changes. +* Run unit tests, type check, and lint locally (or rely on CI) **before** requesting review. +* A PR without passing tests does not get approval. +* New code paths require coverage. No coverage = no approval. + +## Code review tone + +Hold a high bar. PRs with obvious mistakes, missing tests, hardcoded values, or policy violations get firm, specific review comments citing what's wrong and what the fix is. Cite the file and line. Suggest the fix when you know it. Don't sugarcoat — but be professional and constructive. "This looks wrong" is not a review comment. + +## Hardcoded values + +* **Colors** use CSS variables / theme tokens. Never raw hex in components. +* **Strings** use constants or i18n. No magic strings. +* **Numbers** that aren't trivially obvious go in named constants. +* **No magic numbers** in business logic. + +## Secrets in code + +Secrets never touch source. See the `safety` skill for the SealedSecrets workflow. If your implementation requires a Kubernetes secret you cannot create, file an issue for the agent who owns the SealedSecrets workflow rather than committing a plaintext value. + +## Releases and versioning + +CartSnitch CI uses **CalVer** (`YYYY.MM.DD[.N]`) for image tags. The CI also publishes `latest` and `sha-`. Do not introduce other versioning schemes (e.g., custom SemVer for application images). Library packages may use SemVer where the upstream conventions require it. + +## Container images + +Push to `ghcr.io/cartsnitch/` only. Never Docker Hub for first-party images. + +## Task decomposition (for delegators) + +Every delegated task MUST be structured so the assignee can complete it without ambiguity: + +* Single, atomic unit of work. If the task requires more than ~3 files to change, split it into multiple tasks. +* Never delegate tasks requiring architectural judgment or ambiguous scope — make those decisions yourself first, then delegate the concrete action. +* Include relevant context, examples, or code snippets when the action is non-obvious. + +### Task description template + +``` +## What +[One sentence: the specific action to take] + +## Where +[Exact repo, branch, file paths] + +## Why +[One sentence: business/technical reason] + +## How +[Step-by-step instructions, no ambiguity] + +## Acceptance Criteria +- [ ] [Specific, verifiable condition] + +## Context +[Code snippets, links, or prior decisions needed to complete the task] +``` + +## 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. diff --git a/skills/safety/SKILL.md b/skills/safety/SKILL.md new file mode 100644 index 0000000..de566fc --- /dev/null +++ b/skills/safety/SKILL.md @@ -0,0 +1,46 @@ +--- +name: safety +description: > + Non-negotiable safety rules for all CartSnitch agents. Covers secret + handling, destructive-action gating, the SealedSecrets workflow, the + canonical tool list (vs. the alternatives we don't use), the no-Dependabot + policy, and the escalation protocol when an action's safety is uncertain. +--- + +# Safety + +The following rules apply to every CartSnitch agent without exception. + +## Non-negotiable rules + +* **Never exfiltrate secrets or private data.** This includes API keys, tokens, PEM files, database credentials, kubeconfig contents, and any value sourced from a secret reference in your adapter config. Never log, comment, or return these values in any output — including PR descriptions, Paperclip / GitHub issue comments, discussions, and chat responses. + +* **Seek board approval before destructive actions.** "Destructive" means: deleting resources, dropping tables, wiping namespaces, force-pushing branches, resetting git history, removing secrets, or any operation that cannot be undone without restoring from backup. Use `request_board_approval` and set the source issue to `blocked` until approved. + +* **Never commit plaintext secrets.** Kubernetes secrets go through Bitnami Sealed Secrets (`kubeseal`). Application credentials go in environment variables injected at runtime — never hardcoded in source. + +* **Never `kubectl apply` against production (`cartsnitch`) or UAT (`cartsnitch-uat`).** Both are Flux-managed. Manifest changes go through a PR to `cartsnitch/infra` and are reconciled by Flux. The `cartsnitch-dev` namespace permits direct kubectl use for iteration; secrets there should still follow the SealedSecrets pattern when sensitive. + +* **Never `kubectl create secret` in production.** All secrets — at every environment — go through SealedSecrets, encrypted with `kubeseal`, committed as `SealedSecret` resources to `cartsnitch/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 run `tofu` directly.** Terraform goes through the Flux OpenTofu Controller via a PR to `cartsnitch/infra`. + +## 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 + OAuth2 via Authentik. Auth0, Okta, Entra-ID are also supported when required. **Never build custom authentication.** +* **Dependency updates:** Mend Renovate. **Dependabot is not used and will not be used.** Do not configure it. If you encounter Dependabot configuration anywhere, treat it as a policy violation and flag it. +* **Container registry:** `ghcr.io/cartsnitch/` — no Docker Hub for first-party images. +* **Browser automation:** the `playwright` MCP server (`http://playwright:8931/mcp`). Never run Playwright locally or install browser binaries. Target dev (`cartsnitch.dev.farh.net`) — never test production. + +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. + +## 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. diff --git a/skills/sdlc/SKILL.md b/skills/sdlc/SKILL.md new file mode 100644 index 0000000..32843b5 --- /dev/null +++ b/skills/sdlc/SKILL.md @@ -0,0 +1,192 @@ +--- +name: sdlc +description: > + Software development lifecycle for CartSnitch. Covers GitHub 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 GitHub-origin issue + board-approval gate, and the cc-cpfarhood visibility rule. +--- + +# Software Development Lifecycle + +## GitHub authentication + +**Invoke the `github-app-token` skill** before any GitHub operation. It generates a short-lived installation token and writes it to `$GH_CONFIG_DIR/.gh-token` (or `$AGENT_HOME/.gh-token` as fallback) and authenticates `gh` automatically. **Never** run `gh auth login` — it hangs headless agents. Token expires after ~1 hour; re-invoke to regenerate. + +GitHub is the **primary source of truth**. Every Paperclip issue must have a corresponding GitHub issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified. + +## GitHub-origin issue policy — board approval required + +If a task originated from GitHub (`originKind: "github"`), **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: GitHub issue", + "summary": "Summarize what the GitHub 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. + +## 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`) | + +**Engineers always target `dev`** — never `uat` or `main` directly. Feature branches: `/`. + +## 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. + +```bash +gh pr create --base dev --title "..." --body "... cc @cpfarhood" +``` + +GitHub branch protection requires CI checks (lint, test, build-and-push). Governance is enforced through the Paperclip SDLC — GitHub-native review approvals are not required because all agents share a GitHub App identity. Paperclip approval tracking is the authoritative record. + +## PR review & merge policy + +### Dev branch (`dev`) +- **QA** (Checkout Charlie) reviews the PR. Approve → hand to CTO. Fail → back to engineer directly with exact details. +- **CTO** (Savannah Savings) reviews. Approve → CTO merges the `dev` PR. Fail → back to engineer. + +### UAT branch (`uat`) +- **CTO** opens and merges a `dev` → `uat` PR (single approval). + +### Main branch (`main`) +- **CEO** (Coupon Carl) reviews and merges the `uat` → `main` PR. + +`@cpfarhood` is cc'd for visibility on all PRs — never as a reviewer. + +## SDLC pipeline + +### Product analysis (feature intake) + +* Feature requests arrive at the CEO via Paperclip or GitHub Issues. +* CEO delegates to CMO (Markdown Martha) for review. +* CMO: Accepted → CEO routes to CTO for work breakdown. Backlogged → CEO handles prioritization. Denied → closed as unplanned. +* CTO breaks accepted work into atomic tasks and assigns to Engineering. + +### Phase 1 — Dev + +1. **Engineer** branches from `dev`, writes code. GitOps deploys to dev on demand — no approvals needed for dev-environment deployments during development. +2. **Engineer** opens a PR against `dev`. CI must pass. +3. **QA (Checkout Charlie)** reviews the PR. Fail → back to engineer. +4. QA approves and hands off to CTO. +5. **CTO (Savannah Savings)** reviews the PR. Fail → back to engineer. +6. **CTO** merges the dev PR. +7. **CI** builds and deploys automatically to Dev (`https://cartsnitch.dev.farh.net`). + +### Phase 2 — UAT promotion + +8. **CTO** opens and merges a PR from `dev` to `uat`. +9. **CI** builds and deploys automatically to UAT (`https://cartsnitch.uat.farh.net`). +10. **CTO** creates a UAT regression task for **Deal Dottie** immediately after promoting. + +### Phase 3 — UAT testing & security + +11. **UAT (Deal Dottie)** runs full regression against UAT — every feature, old and new, no exceptions. +12. UAT fail → CTO redistributes to engineer (return to Phase 1). +13. UAT pass → **Security Engineer (Stockboy Steve)** performs a security code review of the changes. +14. Security fail → CTO redistributes to engineer (return to Phase 1). + +### Phase 4 — Production + +15. Security pass → **CEO (Coupon Carl)** reviews and merges the production PR (`uat → main`). Fail → back to CTO. +16. **CI** deploys automatically to Production (`https://cartsnitch.farh.net`). + +### Hierarchy rules + +* CTO rejections at Dev go directly to the engineer (not back through QA). +* UAT failures (Deal Dottie) go to CTO — CTO cascades to engineer. +* Security failures (Stockboy Steve) go to CTO — CTO cascades to engineer. +* CEO rejections at Prod go to CTO. + +> **Note on penetration testing:** Stockboy Steve performs scheduled penetration testing against Prod independently of the PR workflow. Board-authorized. Not triggered per-PR. + +## Handoff protocol — mandatory + +Every handoff to another agent requires ALL THREE steps: + +### 1. Explicit assignment + +`PATCH /api/issues/{id}` with `assigneeAgentId: ""`. Mentioning is NOT a handoff — the agent won't wake without explicit assignment. + +### 2. Status = `todo` + +Every handoff sets `status: "todo"`. Never `in_review`, never `backlog` — both are invisible in inbox-lite and the receiver won't wake. + +### 3. Release checkout + +``` +POST /api/issues/{issueId}/release +Headers: Authorization: Bearer $PAPERCLIP_API_KEY, X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID +``` + +Without this release, the receiving agent cannot check out the issue. + +**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. + +## Infrastructure + +* **Production:** namespace `cartsnitch`, FQDN `cartsnitch.farh.net` +* **UAT:** namespace `cartsnitch-uat`, FQDN `cartsnitch.uat.farh.net` +* **Dev:** namespace `cartsnitch-dev`, FQDN `cartsnitch.dev.farh.net` +* **Auth:** Better-Auth + OAuth2 via Authentik OIDC at `https://auth.farh.net` (credentials in `authentik-credentials` secret in the relevant namespace). Authentik / Auth0 / Okta / Entra-ID are all supported. **Never build custom auth.** +* **Cluster:** Kubernetes — cluster-wide read; read/write on `cartsnitch-dev` and `cartsnitch-uat`; read-only on `cartsnitch` (production). +* **Gateways:** `istio-external` (publicly accessible) and `istio-internal` (internal only) in `gateway-system`. +* **Container registry:** `ghcr.io/cartsnitch/` only. + +## Deployment — 2-stage Flux GitOps + +**Stage 1 — CI (GitHub Actions, runs in each application repo):** +- Triggered automatically on every merge to `main` +- Builds and tags the Docker image: CalVer (`YYYY.MM.DD[.N]`), `latest`, and `sha-` +- Pushes tagged images to `ghcr.io/cartsnitch/` +- Creates a CalVer git tag in the source repo + +**Stage 2 — GitOps (Flux, managed externally):** +- Flux watches `cartsnitch/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` → `cartsnitch-dev`, `apps/overlays/uat` → `cartsnitch-uat`, `apps/overlays/prod` → `cartsnitch`. +- 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 `cartsnitch/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 `cartsnitch/infra` to update the relevant overlay; merge after kustomize CI passes. +3. Flux reconciles `cartsnitch/infra` on merge and rolls out the updated pods. + +**To force a rollout without a manifest change** (e.g., pick up a new `:latest` on stuck nodes): +```bash +kubectl rollout restart deployment/ -n +``` + +## Infrastructure as Code + +Terraform (OpenTofu) is deployed via the **Flux OpenTofu Controller** in a GitOps fashion. Submit Terraform configurations via a PR to `cartsnitch/infra` — the tofu controller reconciles them on merge. Use for Authentik configuration, DNS, or other infra provisioning. + +**Never run `tofu` directly.** Never `kubectl apply` against production. Production changes go through Flux only. + +## External communication + +When communicating in any context visible outside the CartSnitch 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`).