-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.pre-commit-config.yaml
More file actions
125 lines (125 loc) · 5.5 KB
/
Copy path.pre-commit-config.yaml
File metadata and controls
125 lines (125 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
exclude: mkdocs.yml
- id: check-added-large-files
args:
- --maxkb=500
- id: check-merge-conflict
- id: detect-private-key
- id: detect-aws-credentials
args:
- --allow-missing-credentials
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.5
hooks:
- id: ruff
args:
- --fix
- id: ruff-format
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args:
- --baseline
- .secrets.baseline
# UAT hash-pin registries (tests/acceptance/uat/data/*_registry.json,
# council D-22/kimi F12-F13) store nothing but sha256 content hashes,
# by design -- exactly what a "Hex High Entropy String" detector is
# built to flag, and exactly what it should ignore here: there is no
# secret to leak, only a pinned digest of a committed, public file.
# Council manifests (docs/architecture/plan-integration/council/*/manifest.json)
# carry the brief and system-prompt sha256 so a seat receipt can be tied to
# the exact text it answered -- again a digest of a committed file, not a key.
# Plan-integration receipts (docs/architecture/plan-integration/receipts/*.json)
# are the same class: the verification receipt records the golden fixture's
# sha256 and the UAT redacted summary carries the rubric hash and the
# private bundle's manifest digest (council D-22) -- every one a digest the
# redaction rules allow out precisely because it identifies without revealing.
exclude: |
(?x)^(
packages/studyloop/tests/acceptance/uat/data/.*_registry\.json|
docs/architecture/plan-integration/council/.*/manifest.*\.json|
docs/architecture/plan-integration/receipts/.*\.json
)$
- repo: https://github.com/PyCQA/bandit
rev: 1.8.3
hooks:
- id: bandit
name: bandit (SAST)
args:
- --recursive
# CLI tool: list-form subprocess argv to fixed binaries (B603/B606/B607),
# the stdlib subprocess import itself (B404), test-fixture/doctor-output
# strings that merely look like credentials (B105-107), try/except:pass
# on documented best-effort paths (B110), urllib on fixed local URLs
# (B310), --lan's intentional 0.0.0.0 bind (B104), and asserts outside
# any request path (B101). B602 (shell=True) has its one real hit
# suppressed with a specific `# nosec B602` (practice.py) rather than
# skipped here. B608 (dynamic SQL) is skipped project-wide because every
# hit -- verified individually, see agents/02-security.md in the 2026-09
# remediation review -- interpolates only a server-side allowlisted
# column name or a `?`-placeholder count; actual values always go
# through bound parameters, so there is no real SQL-injection surface
# for this rule to catch here.
- --skip
- B101,B104,B105,B106,B107,B108,B110,B310,B404,B603,B606,B607,B608
- packages/
- repo: local
hooks:
- id: check-commit-author
name: Check commit author is NetDevAutomate
entry: >-
bash -c '
author="${GIT_AUTHOR_NAME:-$(git config user.name)}";
email="${GIT_AUTHOR_EMAIL:-$(git config user.email)}";
cname="${GIT_COMMITTER_NAME:-$(git config user.name)}";
cemail="${GIT_COMMITTER_EMAIL:-$(git config user.email)}";
if [ "$author" != "NetDevAutomate" ] || [ "$email" != "andy.taylor@mail.com" ] ||
[ "$cname" != "NetDevAutomate" ] || [ "$cemail" != "andy.taylor@mail.com" ]; then
echo "ERROR: Commits must be authored by NetDevAutomate <andy.taylor@mail.com>";
echo " author: $author <$email>";
echo " committer: $cname <$cemail>";
echo "Fix: git config user.name NetDevAutomate && git config user.email andy.taylor@mail.com";
echo "(and do not pass --author or set GIT_AUTHOR_NAME/GIT_COMMITTER_NAME)";
exit 1; fi'
language: system
always_run: true
pass_filenames: false
stages: [pre-commit]
- id: no-aws-tokens
name: Check for AWS tokens
entry: (?i)(AWS_BEARER_TOKEN\w*|aws_access_key_id|aws_secret_access_key)\s*[=:]\s*["']?[A-Za-z0-9/+=]{20,}
language: pygrep
types:
- text
# trufflehog (added 2026-09-15): provider-specific credential detectors on the
# staged changes -- AWS/Bedrock, GitHub, OpenAI, Anthropic, Slack, ... -- as
# a second, independent layer under detect-secrets' entropy heuristics. The
# wrapper consumes trufflehog's JSON and prints detector/file/line only; the
# raw match is never echoed, so a caught secret cannot leak via the hook's
# own output. Fails on `verified` and `unknown` results alike: an
# revoked or fake key still leaks the shape of a real one. Binary via mise.
# Full-history sweep: `uv run python scripts/security/trufflehog_redacted.py --history`.
- id: trufflehog
name: trufflehog (staged changes, redacted output)
entry: uv run --group dev python scripts/security/trufflehog_redacted.py
language: system
pass_filenames: false
always_run: true
stages: [pre-commit]
# One hook, the same invocation as `just typecheck`, so the commit-time check
# and the release gate cannot disagree. The previous two hooks ran pyright on
# each package's src/ only; a test-only type error (R-51) passed the hook and
# then failed the gate.
- id: pyright
name: pyright (workspace, src + tests — same as `just typecheck`)
language: system
entry: uv run --group dev pyright
pass_filenames: false
files: ^packages/.*\.py$