530ecc74e6
- sdlc: trim to application-repo scope with Phase 1-5 pipeline; engineer self-merges all branches with per-branch prerequisites; move infra, Flux, tofu, and operator-install content out - devops: new skill mirroring groombook/org/skills/devops — owns cartsnitch/infra, Flux GitOps, OpenTofu controller, cluster topology, Flux Image Tag Automation denied policy - safety: add Gitea-origin board-approval gate, board-approval scope section, and adapterConfig.env read-before-write rule - coding-standards: replace "no agent merges their own PR" with the reviews-required-then-engineer-may-merge rule consistent with sdlc - CLAUDE.md: update skill index, branch & merge policy, and SDLC phase summary to reflect engineer-self-merge and the new devops skill Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
91 lines
5.2 KiB
Markdown
91 lines
5.2 KiB
Markdown
---
|
|
name: safety
|
|
description: >
|
|
Non-negotiable safety rules for all CartSnitch agents. Covers secret
|
|
handling, destructive-action gating, the SealedSecrets workflow, kubectl
|
|
scope limits, the Gitea-origin board-approval gate, 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 / Gitea 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`).** The production namespace is Flux-managed. Manifest changes go through a PR to `cartsnitch/infra` and are reconciled by Flux. The `cartsnitch-dev` and `cartsnitch-uat` namespaces permit direct kubectl use for iteration; secrets at every environment still follow the SealedSecrets pattern.
|
|
|
|
* **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 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 `cartsnitch/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.
|
|
|
|
## 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.
|
|
|
|
## 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"`** — see the Gitea-origin issue policy above.
|
|
|
|
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 and set the source issue to `blocked` until the approval resolves.
|