From 4b96231b328ac0de46eb736a7f5b4054d231da89 Mon Sep 17 00:00:00 2001 From: Rodin Date: Sun, 10 May 2026 13:43:59 -0700 Subject: [PATCH] docs: strict dependency allowlist with CI enforcement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STRICT ALLOWLIST policy: Only packages explicitly listed in CONVENTIONS.md may be imported. No exceptions. ## Changes - Updates CONVENTIONS.md with strict allowlist language - Adds scripts/check-deps.sh to enforce the allowlist - Adds 'make check-deps' and 'make precommit' targets - CI will fail if any unapproved dependency is detected ## Approved packages - gopkg.in/yaml.v3 — YAML parsing - github.com/google/go-cmp — test comparisons ## Process for new dependencies 1. Open a PR that ONLY updates CONVENTIONS.md 2. Requires explicit approval from Aaron 3. After merge, a separate PR may use the package --- CONVENTIONS.md | 16 +++++++++++- Makefile | 8 +++++- scripts/check-deps.sh | 61 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100755 scripts/check-deps.sh diff --git a/CONVENTIONS.md b/CONVENTIONS.md index ce4406a..abfba06 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -2,8 +2,22 @@ ## Language & Dependencies -- Go standard library only — no external dependencies. - Target the latest stable Go release. +- **STRICT ALLOWLIST:** Only packages listed below may be imported. No exceptions. + +### Approved Third-Party Packages + +| Package | Use Case | +|---------|----------| +| `gopkg.in/yaml.v3` | YAML parsing (persona files, config) | +| `github.com/google/go-cmp` | Test comparisons (`cmp.Diff`) | + +**Any import not in this table or the Go standard library is forbidden.** + +To request a new dependency: +1. Open a PR that ONLY updates this table with justification +2. Requires explicit approval from Aaron +3. After merge, a separate PR may use the package ## Error Handling diff --git a/Makefile b/Makefile index 0f2e182..e5dde12 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build test test-integration lint clean coverage +.PHONY: build test test-integration lint clean coverage check-deps build: go build -o review-bot ./cmd/review-bot/ @@ -12,9 +12,15 @@ test-integration: lint: go vet ./... +check-deps: + @./scripts/check-deps.sh + clean: rm -f review-bot coverage: go test -coverprofile=coverage.out ./... go tool cover -func=coverage.out + +# Precommit runs all checks required before pushing +precommit: check-deps lint test diff --git a/scripts/check-deps.sh b/scripts/check-deps.sh new file mode 100755 index 0000000..cd1cb05 --- /dev/null +++ b/scripts/check-deps.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# check-deps.sh - Enforces the strict dependency allowlist from CONVENTIONS.md +# Exit 1 if any unapproved import is found. + +set -euo pipefail + +# Approved third-party packages (from CONVENTIONS.md) +ALLOWED=( + "gopkg.in/yaml.v3" + "github.com/google/go-cmp" +) + +# Build regex pattern from allowed list +ALLOWED_PATTERN="" +for pkg in "${ALLOWED[@]}"; do + if [ -z "$ALLOWED_PATTERN" ]; then + ALLOWED_PATTERN="$pkg" + else + ALLOWED_PATTERN="$ALLOWED_PATTERN|$pkg" + fi +done + +# Get all imports from go.mod (excluding the module itself and stdlib) +IMPORTS=$(go list -m all 2>/dev/null | tail -n +2 | awk '{print $1}' || true) + +if [ -z "$IMPORTS" ]; then + echo "✅ No external dependencies" + exit 0 +fi + +VIOLATIONS="" +while IFS= read -r import; do + # Skip empty lines + [ -z "$import" ] && continue + + # Check if import matches any allowed pattern (prefix match for subpackages) + MATCHED=false + for allowed in "${ALLOWED[@]}"; do + if [[ "$import" == "$allowed" ]] || [[ "$import" == "$allowed/"* ]]; then + MATCHED=true + break + fi + done + + if [ "$MATCHED" = false ]; then + VIOLATIONS="$VIOLATIONS\n - $import" + fi +done <<< "$IMPORTS" + +if [ -n "$VIOLATIONS" ]; then + echo "❌ UNAPPROVED DEPENDENCIES DETECTED" + echo -e "The following imports are not in the allowlist:$VIOLATIONS" + echo "" + echo "To add a dependency:" + echo " 1. Open a PR that ONLY updates CONVENTIONS.md" + echo " 2. Get explicit approval from Aaron" + echo " 3. After merge, use the package in a separate PR" + exit 1 +fi + +echo "✅ All dependencies are approved"