Skip to content

Commit e60a2bc

Browse files
Jonathan D.A. Jewellclaude
andcommitted
chore: add RSR enforcement workflows
Added standard enforcement workflows: - CodeQL security scanning - OSSF Scorecard - Code quality checks - Mirror to forges - Guix/Nix policy - Security policy - Well-known standards - Workflow linter - Secret scanner - RSR anti-pattern check - npm/bun blocker - TypeScript blocker 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 9583d73 commit e60a2bc

12 files changed

Lines changed: 629 additions & 116 deletions

.github/workflows/codeql.yml

Lines changed: 25 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,40 @@
1-
# SPDX-License-Identifier: MPL-2.0
2-
# For most projects, this workflow file will not need changing; you simply need
3-
# to commit it to your repository.
4-
#
5-
# You may wish to alter this file to override the set of languages analyzed,
6-
# or to provide custom queries or build logic.
7-
#
8-
# ******** NOTE ********
9-
# We have attempted to detect the languages in your repository. Please check
10-
# the `language` matrix defined below to confirm you have the correct set of
11-
# supported CodeQL languages.
12-
#
13-
name: "CodeQL Advanced"
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: CodeQL Security Analysis
143

154
on:
165
push:
17-
branches: [ "main" ]
6+
branches: [main, master]
187
pull_request:
19-
branches: [ "main" ]
8+
branches: [main, master]
209
schedule:
21-
- cron: '42 20 * * 0'
10+
- cron: '0 6 * * 1'
11+
12+
permissions: read-all
2213

2314
jobs:
2415
analyze:
25-
name: Analyze (${{ matrix.language }})
26-
# Runner size impacts CodeQL analysis time. To learn more, please see:
27-
# - https://gh.io/recommended-hardware-resources-for-running-codeql
28-
# - https://gh.io/supported-runners-and-hardware-resources
29-
# - https://gh.io/using-larger-runners (GitHub.com only)
30-
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
31-
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
16+
runs-on: ubuntu-latest
3217
permissions:
33-
# required for all workflows
34-
security-events: write
35-
36-
# required to fetch internal or private CodeQL packs
37-
packages: read
38-
39-
# only required for workflows in private repositories
40-
actions: read
4118
contents: read
42-
19+
security-events: write
4320
strategy:
4421
fail-fast: false
4522
matrix:
4623
include:
47-
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
48-
# Use `c-cpp` to analyze code written in C, C++ or both
49-
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
50-
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
51-
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
52-
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
53-
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
54-
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
55-
steps:
56-
- name: Checkout repository
57-
uses: actions/checkout@v6.0.1
58-
59-
# Add any setup steps before running the `github/codeql-action/init` action.
60-
# This includes steps like installing compilers or runtimes (`actions/setup-node`
61-
# or others). This is typically only required for manual builds.
62-
# - name: Setup runtime (example)
63-
# uses: actions/setup-example@v1
64-
65-
# Initializes the CodeQL tools for scanning.
66-
- name: Initialize CodeQL
67-
uses: github/codeql-action/init@v4
68-
with:
69-
languages: ${{ matrix.language }}
70-
build-mode: ${{ matrix.build-mode }}
71-
# If you wish to specify custom queries, you can do so here or in a config file.
72-
# By default, queries listed here will override any specified in a config file.
73-
# Prefix the list here with "+" to use these queries and those in the config file.
24+
- language: actions
25+
build-mode: none
7426

75-
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
76-
# queries: security-extended,security-and-quality
77-
78-
# If the analyze step fails for one of the languages you are analyzing with
79-
# "We were unable to automatically build your code", modify the matrix above
80-
# to set the build mode to "manual" for that language. Then modify this step
81-
# to build your code.
82-
# ℹ️ Command-line programs to run using the OS shell.
83-
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
84-
- name: Run manual build steps
85-
if: matrix.build-mode == 'manual'
86-
shell: bash
87-
run: |
88-
echo 'If you are using a "manual" build mode for one or more of the' \
89-
'languages you are analyzing, replace this with the commands to build' \
90-
'your code, for example:'
91-
echo ' make bootstrap'
92-
echo ' make release'
93-
exit 1
94-
95-
- name: Perform CodeQL Analysis
96-
uses: github/codeql-action/analyze@v4
97-
with:
98-
category: "/language:${{matrix.language}}"
27+
steps:
28+
- name: Checkout
29+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
30+
31+
- name: Initialize CodeQL
32+
uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
33+
with:
34+
languages: ${{ matrix.language }}
35+
build-mode: ${{ matrix.build-mode }}
36+
37+
- name: Perform CodeQL Analysis
38+
uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
39+
with:
40+
category: "/language:${{ matrix.language }}"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: Guix/Nix Package Policy
3+
on: [push, pull_request]
4+
5+
permissions: read-all
6+
7+
jobs:
8+
check:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
steps:
13+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
14+
- name: Enforce Guix primary / Nix fallback
15+
run: |
16+
# Check for package manager files
17+
HAS_GUIX=$(find . -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" 2>/dev/null | head -1)
18+
HAS_NIX=$(find . -name "*.nix" 2>/dev/null | head -1)
19+
20+
# Block new package-lock.json, yarn.lock, Gemfile.lock, etc.
21+
NEW_LOCKS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E 'package-lock\.json|yarn\.lock|Gemfile\.lock|Pipfile\.lock|poetry\.lock|cargo\.lock' || true)
22+
if [ -n "$NEW_LOCKS" ]; then
23+
echo "⚠️ Lock files detected. Prefer Guix manifests for reproducibility."
24+
fi
25+
26+
# Prefer Guix, fallback to Nix
27+
if [ -n "$HAS_GUIX" ]; then
28+
echo "✅ Guix package management detected (primary)"
29+
elif [ -n "$HAS_NIX" ]; then
30+
echo "✅ Nix package management detected (fallback)"
31+
else
32+
echo "ℹ️ Consider adding guix.scm or flake.nix for reproducible builds"
33+
fi
34+
35+
echo "✅ Package policy check passed"

.github/workflows/mirror.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-License-Identifier: MPL-2.0
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
22
# SPDX-FileCopyrightText: 2025 Jonathan D.A. Jewell
33
name: Mirror to Git Forges
44

@@ -126,10 +126,16 @@ jobs:
126126
with:
127127
fetch-depth: 0
128128

129+
- name: Setup Rust
130+
uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # stable
131+
with:
132+
toolchain: stable
133+
129134
- name: Install Radicle
130135
run: |
131-
curl -sSf https://radicle.xyz/install | sh
132-
echo "$HOME/.radicle/bin" >> $GITHUB_PATH
136+
# Install via cargo (safer than curl|sh)
137+
cargo install radicle-cli --locked
138+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
133139
134140
- name: Mirror to Radicle
135141
run: |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: NPM/Bun Blocker
3+
on: [push, pull_request]
4+
5+
permissions: read-all
6+
7+
jobs:
8+
check:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
steps:
13+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
14+
- name: Block npm/bun
15+
run: |
16+
if [ -f "package-lock.json" ] || [ -f "bun.lockb" ] || [ -f ".npmrc" ]; then
17+
echo "❌ npm/bun artifacts detected. Use Deno instead."
18+
exit 1
19+
fi
20+
echo "✅ No npm/bun violations"

.github/workflows/quality.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: Code Quality
3+
on: [push, pull_request]
4+
5+
6+
permissions: read-all
7+
8+
jobs:
9+
lint:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
steps:
14+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
15+
16+
- name: Check file permissions
17+
run: |
18+
find . -type f -perm /111 -name "*.sh" | head -10 || true
19+
20+
- name: Check for secrets
21+
uses: trufflesecurity/trufflehog@05cccb53bc9e13bc6d17997db5a6bcc3df44bf2f # v3.92.3
22+
with:
23+
path: ./
24+
base: ${{ github.event.pull_request.base.sha || github.event.before }}
25+
head: ${{ github.sha }}
26+
continue-on-error: true
27+
28+
- name: Check TODO/FIXME
29+
run: |
30+
echo "=== TODOs ==="
31+
grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.rs" --include="*.res" --include="*.py" --include="*.ex" . | head -20 || echo "None found"
32+
33+
- name: Check for large files
34+
run: |
35+
find . -type f -size +1M -not -path "./.git/*" | head -10 || echo "No large files"
36+
37+
- name: EditorConfig check
38+
uses: editorconfig-checker/action-editorconfig-checker@8c9b118d446fce7e6410b6c0a3ce2f83bd04e97a # v2.1.0
39+
continue-on-error: true
40+
41+
docs:
42+
runs-on: ubuntu-latest
43+
permissions:
44+
contents: read
45+
steps:
46+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
47+
- name: Check documentation
48+
run: |
49+
MISSING=""
50+
[ ! -f "README.md" ] && [ ! -f "README.adoc" ] && MISSING="$MISSING README"
51+
[ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ] && MISSING="$MISSING LICENSE"
52+
[ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] && MISSING="$MISSING CONTRIBUTING"
53+
54+
if [ -n "$MISSING" ]; then
55+
echo "::warning::Missing docs:$MISSING"
56+
else
57+
echo "✅ Core documentation present"
58+
fi
Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,92 @@
1-
# SPDX-License-Identifier: MPL-2.0
2-
name: RSR Language Policy
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# RSR Anti-Pattern CI Check
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
#
5+
# Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm
6+
# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme
7+
8+
name: RSR Anti-Pattern Check
39

410
on:
511
push:
6-
branches: [main]
12+
branches: [main, master, develop]
713
pull_request:
8-
branches: [main]
14+
branches: [main, master, develop]
15+
916

1017
permissions: read-all
1118

1219
jobs:
13-
check-banned-patterns:
14-
name: Check for banned languages/patterns
20+
antipattern-check:
1521
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
1624
steps:
17-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
18-
25+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
26+
1927
- name: Check for TypeScript
2028
run: |
21-
if find . -name "*.ts" -o -name "*.tsx" | grep -v node_modules | grep -q .; then
22-
echo "::error::TypeScript files found! Use ReScript instead (per RSR policy)"
29+
# Exclude bindings/deno/ - those are Deno FFI files using Deno.dlopen, not plain TypeScript
30+
# Exclude .d.ts files - those are TypeScript type declarations for ReScript FFI
31+
TS_FILES=$(find . \( -name "*.ts" -o -name "*.tsx" \) | grep -v node_modules | grep -v 'bindings/deno' | grep -v '\.d\.ts$' || true)
32+
if [ -n "$TS_FILES" ]; then
33+
echo "❌ TypeScript files detected - use ReScript instead"
34+
echo "$TS_FILES"
2335
exit 1
2436
fi
25-
echo " No TypeScript files found"
26-
37+
echo " No TypeScript files (Deno FFI bindings excluded)"
38+
2739
- name: Check for Go
2840
run: |
2941
if find . -name "*.go" | grep -q .; then
30-
echo "::error::Go files found! Use Rust instead (per RSR policy)"
42+
echo "❌ Go files detected - use Rust/WASM instead"
43+
find . -name "*.go"
3144
exit 1
3245
fi
33-
echo " No Go files found"
34-
35-
- name: Check for npm/Node artifacts
46+
echo " No Go files"
47+
48+
- name: Check for Python (non-SaltStack)
3649
run: |
37-
if [ -f "package-lock.json" ] || [ -d "node_modules" ]; then
38-
echo "::error::npm artifacts found! Use Deno instead (per RSR policy)"
50+
PY_FILES=$(find . -name "*.py" | grep -v salt | grep -v _states | grep -v _modules | grep -v pillar | grep -v venv | grep -v __pycache__ || true)
51+
if [ -n "$PY_FILES" ]; then
52+
echo "❌ Python files detected - only allowed for SaltStack"
53+
echo "$PY_FILES"
3954
exit 1
4055
fi
41-
echo " No npm artifacts found"
42-
43-
- name: Check for Python (non-SaltStack)
56+
echo " No non-SaltStack Python files"
57+
58+
- name: Check for npm lockfiles
4459
run: |
45-
banned_py=$(find . -name "*.py" | grep -v -E "(salt|pillar|states|_modules|_states)" | head -1)
46-
if [ -n "$banned_py" ]; then
47-
echo "::error::Python files found outside SaltStack! Use ReScript/Rust (per RSR policy)"
60+
if [ -f "package-lock.json" ] || [ -f "yarn.lock" ]; then
61+
echo "❌ npm/yarn lockfile detected - use Deno instead"
4862
exit 1
4963
fi
50-
echo " No banned Python files found"
51-
52-
- name: Check for Makefiles
64+
echo " No npm lockfiles"
65+
66+
- name: Check for tsconfig
5367
run: |
54-
if [ -f "Makefile" ] || [ -f "makefile" ] || find . -name "*.mk" | grep -q .; then
55-
echo "::error::Makefile found! Use Justfile or Mustfile instead (per RSR policy)"
68+
if [ -f "tsconfig.json" ]; then
69+
echo "❌ tsconfig.json detected - use ReScript instead"
5670
exit 1
5771
fi
58-
echo "✓ No Makefiles found"
72+
echo "✅ No tsconfig.json"
73+
74+
- name: Verify Deno presence (if package.json exists)
75+
run: |
76+
if [ -f "package.json" ]; then
77+
if [ ! -f "deno.json" ] && [ ! -f "deno.jsonc" ]; then
78+
echo "⚠️ Warning: package.json without deno.json - migration recommended"
79+
fi
80+
fi
81+
echo "✅ Deno configuration check complete"
82+
83+
- name: Summary
84+
run: |
85+
echo "╔════════════════════════════════════════════════════════════╗"
86+
echo "║ RSR Anti-Pattern Check Passed ✅ ║"
87+
echo "║ ║"
88+
echo "║ Allowed: ReScript, Deno, WASM, Rust, OCaml, Haskell, ║"
89+
echo "║ Guile/Scheme, SaltStack (Python) ║"
90+
echo "║ ║"
91+
echo "║ Blocked: TypeScript, Go, npm, Python (non-Salt) ║"
92+
echo "╚════════════════════════════════════════════════════════════╝"

0 commit comments

Comments
 (0)