Skip to content

Commit bc59bdc

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 6718bd3 commit bc59bdc

12 files changed

Lines changed: 115 additions & 62 deletions

.github/workflows/codeql.yml

Lines changed: 5 additions & 5 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
name: CodeQL Security Analysis
33

44
on:
@@ -21,20 +21,20 @@ jobs:
2121
fail-fast: false
2222
matrix:
2323
include:
24-
- language: rust
24+
- language: actions
2525
build-mode: none
2626

2727
steps:
2828
- name: Checkout
29-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
29+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
3030

3131
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.28.1
32+
uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
3333
with:
3434
languages: ${{ matrix.language }}
3535
build-mode: ${{ matrix.build-mode }}
3636

3737
- name: Perform CodeQL Analysis
38-
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.28.1
38+
uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
3939
with:
4040
category: "/language:${{ matrix.language }}"
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# SPDX-License-Identifier: MPL-2.0
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
22
name: Guix/Nix Package Policy
3-
43
on: [push, pull_request]
54

65
permissions: read-all
@@ -11,19 +10,19 @@ jobs:
1110
permissions:
1211
contents: read
1312
steps:
14-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
13+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1514
- name: Enforce Guix primary / Nix fallback
1615
run: |
1716
# Check for package manager files
1817
HAS_GUIX=$(find . -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" 2>/dev/null | head -1)
1918
HAS_NIX=$(find . -name "*.nix" 2>/dev/null | head -1)
20-
19+
2120
# Block new package-lock.json, yarn.lock, Gemfile.lock, etc.
2221
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)
2322
if [ -n "$NEW_LOCKS" ]; then
2423
echo "⚠️ Lock files detected. Prefer Guix manifests for reproducibility."
2524
fi
26-
25+
2726
# Prefer Guix, fallback to Nix
2827
if [ -n "$HAS_GUIX" ]; then
2928
echo "✅ Guix package management detected (primary)"
@@ -32,5 +31,5 @@ jobs:
3231
else
3332
echo "ℹ️ Consider adding guix.scm or flake.nix for reproducible builds"
3433
fi
35-
34+
3635
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: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# SPDX-License-Identifier: MPL-2.0
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
22
name: Code Quality
3-
43
on: [push, pull_request]
54

5+
66
permissions: read-all
77

88
jobs:
@@ -11,46 +11,46 @@ jobs:
1111
permissions:
1212
contents: read
1313
steps:
14-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
15-
14+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
15+
1616
- name: Check file permissions
1717
run: |
1818
find . -type f -perm /111 -name "*.sh" | head -10 || true
19-
19+
2020
- name: Check for secrets
21-
uses: trufflesecurity/trufflehog@ef6e76c3c4023279497fab4721ffa071a722fd05 # v3.88.3
21+
uses: trufflesecurity/trufflehog@05cccb53bc9e13bc6d17997db5a6bcc3df44bf2f # v3.92.3
2222
with:
2323
path: ./
2424
base: ${{ github.event.pull_request.base.sha || github.event.before }}
2525
head: ${{ github.sha }}
2626
continue-on-error: true
27-
27+
2828
- name: Check TODO/FIXME
2929
run: |
3030
echo "=== TODOs ==="
3131
grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.rs" --include="*.res" --include="*.py" --include="*.ex" . | head -20 || echo "None found"
32-
32+
3333
- name: Check for large files
3434
run: |
3535
find . -type f -size +1M -not -path "./.git/*" | head -10 || echo "No large files"
36-
36+
3737
- name: EditorConfig check
38-
uses: editorconfig-checker/action-editorconfig-checker@8f4bf2460c5c7f2597a10abb3e0e1c3b7a7df044 # v2.0.0
38+
uses: editorconfig-checker/action-editorconfig-checker@8c9b118d446fce7e6410b6c0a3ce2f83bd04e97a # v2.1.0
3939
continue-on-error: true
4040

4141
docs:
4242
runs-on: ubuntu-latest
4343
permissions:
4444
contents: read
4545
steps:
46-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
46+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
4747
- name: Check documentation
4848
run: |
4949
MISSING=""
5050
[ ! -f "README.md" ] && [ ! -f "README.adoc" ] && MISSING="$MISSING README"
5151
[ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ] && MISSING="$MISSING LICENSE"
5252
[ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] && MISSING="$MISSING CONTRIBUTING"
53-
53+
5454
if [ -n "$MISSING" ]; then
5555
echo "::warning::Missing docs:$MISSING"
5656
else

.github/workflows/rsr-antipattern.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
# RSR Anti-Pattern CI Check
2-
# SPDX-License-Identifier: MPL-2.0
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
34
#
45
# Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm
56
# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme
@@ -12,6 +13,7 @@ on:
1213
pull_request:
1314
branches: [main, master, develop]
1415

16+
1517
permissions: read-all
1618

1719
jobs:
@@ -20,16 +22,19 @@ jobs:
2022
permissions:
2123
contents: read
2224
steps:
23-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
25+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2426

2527
- name: Check for TypeScript
2628
run: |
27-
if find . -name "*.ts" -o -name "*.tsx" | grep -v node_modules | grep -q .; then
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
2833
echo "❌ TypeScript files detected - use ReScript instead"
29-
find . -name "*.ts" -o -name "*.tsx" | grep -v node_modules
34+
echo "$TS_FILES"
3035
exit 1
3136
fi
32-
echo "✅ No TypeScript files"
37+
echo "✅ No TypeScript files (Deno FFI bindings excluded)"
3338
3439
- name: Check for Go
3540
run: |

.github/workflows/scorecard.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# SPDX-License-Identifier: MPL-2.0
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
22
name: OSSF Scorecard
3-
43
on:
54
push:
65
branches: [main, master]
76
schedule:
87
- cron: '0 4 * * *'
8+
workflow_dispatch:
99

1010
permissions: read-all
1111

@@ -15,19 +15,18 @@ jobs:
1515
permissions:
1616
security-events: write
1717
id-token: write
18-
contents: read
1918
steps:
20-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
19+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2120
with:
2221
persist-credentials: false
2322

2423
- name: Run Scorecard
25-
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
24+
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.3.1
2625
with:
2726
results_file: results.sarif
2827
results_format: sarif
2928

3029
- name: Upload results
31-
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.28.1
30+
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.31.8
3231
with:
3332
sarif_file: results.sarif

.github/workflows/secret-scanner.yml

Lines changed: 5 additions & 5 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
# Prevention workflow - scans for hardcoded secrets before they reach main
33
name: Secret Scanner
44

@@ -13,19 +13,19 @@ jobs:
1313
trufflehog:
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
16+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
1717
with:
1818
fetch-depth: 0 # Full history for scanning
1919

2020
- name: TruffleHog Secret Scan
21-
uses: trufflesecurity/trufflehog@ef6e76c3c4023279497fab4721ffa071a722fd05 # v3
21+
uses: trufflesecurity/trufflehog@8a8ef8526528d8a4ff3e2c90be08e25ef8efbd9b # v3
2222
with:
2323
extra_args: --only-verified --fail
2424

2525
gitleaks:
2626
runs-on: ubuntu-latest
2727
steps:
28-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
28+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
2929
with:
3030
fetch-depth: 0
3131

@@ -39,7 +39,7 @@ jobs:
3939
runs-on: ubuntu-latest
4040
if: hashFiles('**/Cargo.toml') != ''
4141
steps:
42-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
42+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
4343

4444
- name: Check for hardcoded secrets in Rust
4545
run: |
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# SPDX-License-Identifier: MPL-2.0
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
22
name: Security Policy
3-
43
on: [push, pull_request]
54

65
permissions: read-all
@@ -11,34 +10,34 @@ jobs:
1110
permissions:
1211
contents: read
1312
steps:
14-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
13+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1514
- name: Security checks
1615
run: |
1716
FAILED=false
18-
17+
1918
# Block MD5/SHA1 for security (allow for checksums/caching)
2019
WEAK_CRYPTO=$(grep -rE 'md5\(|sha1\(' --include="*.py" --include="*.rb" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" . 2>/dev/null | grep -v 'checksum\|cache\|test\|spec' | head -5 || true)
2120
if [ -n "$WEAK_CRYPTO" ]; then
2221
echo "⚠️ Weak crypto (MD5/SHA1) detected. Use SHA256+ for security:"
2322
echo "$WEAK_CRYPTO"
2423
fi
25-
24+
2625
# Block HTTP URLs (except localhost)
2726
HTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true)
2827
if [ -n "$HTTP_URLS" ]; then
2928
echo "⚠️ HTTP URLs found. Use HTTPS:"
3029
echo "$HTTP_URLS"
3130
fi
32-
31+
3332
# Block hardcoded secrets patterns
3433
SECRETS=$(grep -rEi '(api_key|apikey|secret_key|password)\s*[=:]\s*["\x27][A-Za-z0-9+/=]{20,}' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.env" . 2>/dev/null | grep -v 'example\|sample\|test\|mock\|placeholder' | head -3 || true)
3534
if [ -n "$SECRETS" ]; then
3635
echo "❌ Potential hardcoded secrets detected!"
3736
FAILED=true
3837
fi
39-
38+
4039
if [ "$FAILED" = true ]; then
4140
exit 1
4241
fi
43-
42+
4443
echo "✅ Security policy check passed"

.github/workflows/ts-blocker.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: TypeScript/JavaScript 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 new TypeScript/JavaScript
15+
run: |
16+
NEW_TS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(ts|tsx)$' | grep -v '\.gen\.' || true)
17+
NEW_JS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(js|jsx)$' | grep -v '\.res\.js$' | grep -v '\.gen\.' | grep -v 'node_modules' || true)
18+
19+
if [ -n "$NEW_TS" ] || [ -n "$NEW_JS" ]; then
20+
echo "❌ New TS/JS files detected. Use ReScript instead."
21+
[ -n "$NEW_TS" ] && echo "$NEW_TS"
22+
[ -n "$NEW_JS" ] && echo "$NEW_JS"
23+
exit 1
24+
fi
25+
echo "✅ ReScript policy enforced"

0 commit comments

Comments
 (0)