-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.pre-commit-config.yaml
More file actions
129 lines (129 loc) · 5.78 KB
/
Copy path.pre-commit-config.yaml
File metadata and controls
129 lines (129 loc) · 5.78 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
126
127
128
129
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.
# Learning-tier council manifests and receipts (2026-09-19) are the same two
# classes: brief/system-prompt digests and pre-registration fingerprints.
exclude: |
(?x)^(
packages/studyloop/tests/acceptance/uat/data/.*_registry\.json|
docs/architecture/plan-integration/council/.*/manifest.*\.json|
docs/architecture/plan-integration/receipts/.*\.json|
docs/architecture/learning-tier/council/.*/manifest.*\.json|
docs/architecture/learning-tier/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$