Skip to content

Commit 943ec75

Browse files
authored
chore: merge dev into main (#32)
2 parents 131e9e8 + 230847a commit 943ec75

17 files changed

Lines changed: 478 additions & 174 deletions

.claude/settings.json

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
"Bash(git log:*)",
88
"Bash(git show:*)",
99
"Bash(git branch:*)",
10+
"Bash(git push:*)",
11+
"Bash(ls:*)",
12+
"Bash(grep:*)",
13+
"Bash(rg:*)",
1014
"Bash(pnpm install)",
1115
"Bash(pnpm lint)",
1216
"Bash(pnpm lint:fix)",
@@ -16,11 +20,56 @@
1620
"Bash(pnpm check:fix)"
1721
],
1822
"deny": [
19-
"Bash(git push:*)",
23+
"Bash(git push --force:*)",
24+
"Bash(git push -f:*)",
25+
"Bash(git push --force-with-lease:*)",
2026
"Bash(git reset --hard:*)",
2127
"Bash(git clean -f:*)",
2228
"Bash(git checkout --:*)",
23-
"Bash(git branch -D:*)"
29+
"Bash(git branch -D:*)",
30+
"Bash(git filter-branch:*)",
31+
"Bash(git reflog expire:*)",
32+
"Bash(git gc --prune=now:*)",
33+
"Bash(git stash clear:*)",
34+
"Bash(git stash drop:*)",
35+
"Bash(git update-ref -d:*)",
36+
"Bash(git worktree remove --force:*)",
37+
"Bash(gh repo delete:*)",
38+
"Bash(gh release delete:*)",
39+
"Bash(gh secret delete:*)",
40+
"Bash(rm -rf /:*)",
41+
"Bash(sudo rm:*)",
42+
"Bash(chmod -R:*)",
43+
"Bash(chown -R:*)",
44+
"Bash(dd:*)",
45+
"Bash(mkfs:*)",
46+
"Bash(shred:*)",
47+
"Bash(php artisan migrate:fresh:*)",
48+
"Bash(php artisan migrate:reset:*)",
49+
"Bash(php artisan db:wipe:*)",
50+
"Bash(prisma migrate reset:*)",
51+
"Bash(npx prisma migrate reset:*)",
52+
"Bash(prisma db push --force-reset:*)",
53+
"Bash(pnpm db:fresh)",
54+
"Bash(pnpm db:reset)",
55+
"Bash(terraform destroy:*)",
56+
"Bash(terraform apply -auto-approve:*)",
57+
"Bash(terraform state rm:*)",
58+
"Bash(terraform state push:*)",
59+
"Bash(terraform force-unlock:*)",
60+
"Bash(terraform workspace delete:*)",
61+
"Bash(tofu destroy:*)",
62+
"Bash(tofu apply -auto-approve:*)",
63+
"Bash(tofu state rm:*)",
64+
"Bash(tofu state push:*)",
65+
"Bash(tofu force-unlock:*)",
66+
"Bash(tofu workspace delete:*)",
67+
"Bash(aws s3 rb:*)",
68+
"Bash(aws s3 rm:*)",
69+
"Bash(aws ec2 terminate-instances:*)",
70+
"Bash(aws rds delete-db-instance:*)",
71+
"Bash(aws cloudformation delete-stack:*)",
72+
"Bash(aws iam delete-:*)"
2473
]
2574
}
2675
}

.codex/rules/default.rules

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# Codex execution policy — the counterpart to .claude/settings.json.
2+
#
3+
# Same principle: block what wrecks the machine, tears down remote state, or
4+
# destroys work with no recovery path. Ordinary local development is left to
5+
# prompt rather than blocked — rm -rf node_modules, docker volume rm,
6+
# compose down -v, artisan tinker and deleting a remote branch stay usable.
7+
#
8+
# Verify after editing:
9+
# codex execpolicy check --pretty --rules .codex/rules/default.rules -- <command>
10+
11+
# ─────────────────────────── git: work and history ───────────────────────────
12+
13+
prefix_rule(
14+
pattern = ["git", "push", ["--force", "-f", "--force-with-lease"]],
15+
decision = "forbidden",
16+
justification = "Force-push overwrites history other clones already have",
17+
match = ["git push --force", "git push -f origin dev"],
18+
not_match = ["git push", "git push origin dev"],
19+
)
20+
21+
prefix_rule(
22+
pattern = ["git", "reset", "--hard"],
23+
decision = "forbidden",
24+
justification = "Discards uncommitted work with no recovery path",
25+
match = ["git reset --hard", "git reset --hard HEAD~1"],
26+
not_match = ["git reset", "git reset --soft HEAD~1"],
27+
)
28+
29+
prefix_rule(
30+
pattern = ["git", "clean", ["-f", "-fd", "-fdx", "-ffd"]],
31+
decision = "forbidden",
32+
justification = "Deletes untracked files irrecoverably",
33+
match = ["git clean -f", "git clean -fdx"],
34+
not_match = ["git clean -n", "git clean --dry-run"],
35+
)
36+
37+
prefix_rule(
38+
pattern = ["git", "checkout", "--"],
39+
decision = "forbidden",
40+
justification = "Throws away file changes irrecoverably",
41+
match = ["git checkout -- src/main.ts"],
42+
not_match = ["git checkout main", "git checkout -b feat/x"],
43+
)
44+
45+
prefix_rule(
46+
pattern = ["git", "branch", "-D"],
47+
decision = "forbidden",
48+
justification = "Deletes an unmerged branch; -d is the safe form",
49+
match = ["git branch -D feat/x"],
50+
not_match = ["git branch -d feat/x", "git branch"],
51+
)
52+
53+
prefix_rule(
54+
pattern = ["git", ["filter-branch", "filter-repo"]],
55+
decision = "forbidden",
56+
justification = "Rewrites the entire history",
57+
match = ["git filter-branch --tree-filter true HEAD"],
58+
)
59+
60+
prefix_rule(
61+
pattern = ["git", "reflog", "expire"],
62+
decision = "forbidden",
63+
justification = "Destroys the rescue path that survives a hard reset",
64+
match = ["git reflog expire --expire=now --all"],
65+
not_match = ["git reflog"],
66+
)
67+
68+
prefix_rule(
69+
pattern = ["git", "gc", "--prune=now"],
70+
decision = "forbidden",
71+
justification = "Drops unreferenced objects, completing what reflog expire starts",
72+
match = ["git gc --prune=now"],
73+
not_match = ["git gc"],
74+
)
75+
76+
prefix_rule(
77+
pattern = ["git", "stash", ["drop", "clear"]],
78+
decision = "forbidden",
79+
justification = "Stashed work is gone without a reflog entry",
80+
match = ["git stash drop", "git stash clear"],
81+
not_match = ["git stash", "git stash list", "git stash pop"],
82+
)
83+
84+
prefix_rule(
85+
pattern = ["git", "update-ref", "-d"],
86+
decision = "forbidden",
87+
justification = "Deletes a ref directly, bypassing the usual safeguards",
88+
match = ["git update-ref -d refs/heads/dev"],
89+
)
90+
91+
prefix_rule(
92+
pattern = ["git", "worktree", "remove", "--force"],
93+
decision = "forbidden",
94+
justification = "Removes a worktree including uncommitted changes",
95+
match = ["git worktree remove --force ../wt"],
96+
not_match = ["git worktree list", "git worktree remove ../wt"],
97+
)
98+
99+
# ──────────────────────────── github: remote state ───────────────────────────
100+
101+
prefix_rule(
102+
pattern = ["gh", ["repo", "release", "secret"], "delete"],
103+
decision = "forbidden",
104+
justification = "Deletes remote resources; a repo takes issues and PRs with it",
105+
match = ["gh repo delete TitusKirch/scaffold", "gh release delete v1.0.0"],
106+
not_match = ["gh repo view", "gh release list"],
107+
)
108+
109+
# ──────────────────────────── os and storage ─────────────────────────────────
110+
111+
prefix_rule(
112+
pattern = ["rm", ["-rf", "-fr", "-Rf", "-fR"], "/"],
113+
decision = "forbidden",
114+
justification = "Recursive delete from the filesystem root",
115+
match = ["rm -rf /", "rm -rf /etc"],
116+
not_match = ["rm -rf node_modules", "rm -rf dist"],
117+
)
118+
119+
prefix_rule(
120+
pattern = ["sudo", "rm"],
121+
decision = "forbidden",
122+
justification = "Elevated deletion outside the workspace",
123+
match = ["sudo rm -rf /var/lib"],
124+
)
125+
126+
prefix_rule(
127+
pattern = [["chmod", "chown"], "-R"],
128+
decision = "forbidden",
129+
justification = "Recursive ownership or permission changes can break the system",
130+
match = ["chmod -R 777 /", "chown -R root:root /usr"],
131+
not_match = ["chmod +x script.sh"],
132+
)
133+
134+
prefix_rule(
135+
pattern = [["dd", "mkfs", "shred", "fdisk", "parted"]],
136+
decision = "forbidden",
137+
justification = "Writes to block devices; never needed from a repo",
138+
match = ["dd if=/dev/zero of=/dev/sda", "mkfs.ext4 /dev/sdb1"],
139+
)
140+
141+
# ──────────────────────────── databases ──────────────────────────────────────
142+
143+
prefix_rule(
144+
pattern = ["php", "artisan", ["migrate:fresh", "migrate:reset", "db:wipe"]],
145+
decision = "forbidden",
146+
justification = "Rebuilds or empties the database",
147+
match = ["php artisan migrate:fresh --seed", "php artisan db:wipe"],
148+
not_match = ["php artisan migrate", "php artisan tinker"],
149+
)
150+
151+
prefix_rule(
152+
pattern = [["prisma", "npx", "pnpm", "bunx"], "prisma", "migrate", "reset"],
153+
decision = "forbidden",
154+
justification = "Drops and recreates the database",
155+
match = ["npx prisma migrate reset", "bunx prisma migrate reset"],
156+
not_match = ["npx prisma migrate dev", "npx prisma generate"],
157+
)
158+
159+
prefix_rule(
160+
pattern = [["pnpm", "npm", "yarn", "bun"], ["db:fresh", "db:reset"]],
161+
decision = "forbidden",
162+
justification = "Project wrapper around a destructive database task",
163+
match = ["pnpm db:fresh", "npm db:reset"],
164+
not_match = ["pnpm db:migrate", "pnpm db:seed"],
165+
)
166+
167+
prefix_rule(
168+
pattern = ["redis-cli", ["flushall", "flushdb", "FLUSHALL", "FLUSHDB"]],
169+
decision = "forbidden",
170+
justification = "Empties the whole Redis instance",
171+
match = ["redis-cli flushall"],
172+
not_match = ["redis-cli ping"],
173+
)
174+
175+
# ──────────────────── terraform / opentofu: remote state ─────────────────────
176+
177+
prefix_rule(
178+
pattern = [["terraform", "tofu"], ["destroy", "force-unlock"]],
179+
decision = "forbidden",
180+
justification = "Tears down infrastructure or breaks the state lock",
181+
match = ["terraform destroy", "tofu force-unlock 1234"],
182+
not_match = ["terraform plan", "tofu init"],
183+
)
184+
185+
prefix_rule(
186+
pattern = [["terraform", "tofu"], "apply", "-auto-approve"],
187+
decision = "forbidden",
188+
justification = "Applies infrastructure changes without a confirmation step",
189+
match = ["terraform apply -auto-approve"],
190+
not_match = ["terraform apply", "terraform plan"],
191+
)
192+
193+
prefix_rule(
194+
pattern = [["terraform", "tofu"], "state", ["rm", "push"]],
195+
decision = "forbidden",
196+
justification = "Corrupts or orphans remote state",
197+
match = ["terraform state rm aws_instance.web", "tofu state push new.tfstate"],
198+
not_match = ["terraform state list", "terraform state show aws_instance.web"],
199+
)
200+
201+
prefix_rule(
202+
pattern = [["terraform", "tofu"], "workspace", "delete"],
203+
decision = "forbidden",
204+
justification = "Removes a workspace and its state",
205+
match = ["terraform workspace delete staging"],
206+
not_match = ["terraform workspace list", "terraform workspace select prod"],
207+
)
208+
209+
# ──────────────────────────── aws: remote resources ──────────────────────────
210+
211+
prefix_rule(
212+
pattern = ["aws", "s3", ["rb", "rm"]],
213+
decision = "forbidden",
214+
justification = "Deletes buckets or objects",
215+
match = ["aws s3 rb s3://bucket --force", "aws s3 rm s3://bucket --recursive"],
216+
not_match = ["aws s3 ls", "aws s3 cp file s3://bucket/"],
217+
)
218+
219+
prefix_rule(
220+
pattern = ["aws", "ec2", ["terminate-instances", "delete-volume", "delete-snapshot"]],
221+
decision = "forbidden",
222+
justification = "Destroys compute or storage",
223+
match = ["aws ec2 terminate-instances --instance-ids i-123"],
224+
not_match = ["aws ec2 describe-instances"],
225+
)
226+
227+
prefix_rule(
228+
pattern = ["aws", "rds", ["delete-db-instance", "delete-db-cluster"]],
229+
decision = "forbidden",
230+
justification = "Deletes a database instance",
231+
match = ["aws rds delete-db-instance --db-instance-identifier prod"],
232+
not_match = ["aws rds describe-db-instances"],
233+
)
234+
235+
prefix_rule(
236+
pattern = ["aws", "cloudformation", "delete-stack"],
237+
decision = "forbidden",
238+
justification = "Tears down every resource in the stack",
239+
match = ["aws cloudformation delete-stack --stack-name prod"],
240+
not_match = ["aws cloudformation describe-stacks"],
241+
)
242+
243+
prefix_rule(
244+
pattern = ["aws", "iam", ["delete-user", "delete-role", "delete-policy", "delete-group"]],
245+
decision = "forbidden",
246+
justification = "Removes identities other systems depend on",
247+
match = ["aws iam delete-role --role-name deploy"],
248+
not_match = ["aws iam list-roles", "aws iam get-role --role-name deploy"],
249+
)

0 commit comments

Comments
 (0)