Skip to content

Commit 14f93ee

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 18abd9a commit 14f93ee

12 files changed

Lines changed: 635 additions & 60 deletions

.github/workflows/codeql.yml

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
1-
# SPDX-License-Identifier: MPL-2.0
2-
name: CodeQL
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
name: CodeQL Security Analysis
3+
34
on:
45
push:
5-
branches: [main]
6+
branches: [main, master]
67
pull_request:
7-
branches: [main]
8+
branches: [main, master]
89
schedule:
9-
- cron: "0 6 * * 1"
10+
- cron: '0 6 * * 1'
11+
1012
permissions: read-all
13+
1114
jobs:
1215
analyze:
13-
name: Analyze
1416
runs-on: ubuntu-latest
1517
permissions:
16-
actions: read
1718
contents: read
1819
security-events: write
1920
strategy:
2021
fail-fast: false
2122
matrix:
22-
language: [actions]
23+
include:
24+
- language: actions
25+
build-mode: none
26+
2327
steps:
2428
- name: Checkout
25-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
29+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
30+
2631
- name: Initialize CodeQL
27-
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3
32+
uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
2833
with:
2934
languages: ${{ matrix.language }}
30-
- name: Autobuild
31-
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3
35+
build-mode: ${{ matrix.build-mode }}
36+
3237
- name: Perform CodeQL Analysis
33-
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3
38+
uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.28.1
3439
with:
3540
category: "/language:${{ matrix.language }}"
36-
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: 22 additions & 16 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

@@ -14,11 +14,11 @@ jobs:
1414
runs-on: ubuntu-latest
1515
if: vars.GITLAB_MIRROR_ENABLED == 'true'
1616
steps:
17-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
17+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
1818
with:
1919
fetch-depth: 0
2020

21-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
21+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
2222
with:
2323
ssh-private-key: ${{ secrets.GITLAB_SSH_KEY }}
2424

@@ -32,11 +32,11 @@ jobs:
3232
runs-on: ubuntu-latest
3333
if: vars.BITBUCKET_MIRROR_ENABLED == 'true'
3434
steps:
35-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
35+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
3636
with:
3737
fetch-depth: 0
3838

39-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
39+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
4040
with:
4141
ssh-private-key: ${{ secrets.BITBUCKET_SSH_KEY }}
4242

@@ -50,11 +50,11 @@ jobs:
5050
runs-on: ubuntu-latest
5151
if: vars.CODEBERG_MIRROR_ENABLED == 'true'
5252
steps:
53-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
53+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
5454
with:
5555
fetch-depth: 0
5656

57-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
57+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
5858
with:
5959
ssh-private-key: ${{ secrets.CODEBERG_SSH_KEY }}
6060

@@ -68,11 +68,11 @@ jobs:
6868
runs-on: ubuntu-latest
6969
if: vars.SOURCEHUT_MIRROR_ENABLED == 'true'
7070
steps:
71-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
71+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
7272
with:
7373
fetch-depth: 0
7474

75-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
75+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
7676
with:
7777
ssh-private-key: ${{ secrets.SOURCEHUT_SSH_KEY }}
7878

@@ -86,11 +86,11 @@ jobs:
8686
runs-on: ubuntu-latest
8787
if: vars.DISROOT_MIRROR_ENABLED == 'true'
8888
steps:
89-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
89+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
9090
with:
9191
fetch-depth: 0
9292

93-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
93+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
9494
with:
9595
ssh-private-key: ${{ secrets.DISROOT_SSH_KEY }}
9696

@@ -104,11 +104,11 @@ jobs:
104104
runs-on: ubuntu-latest
105105
if: vars.GITEA_MIRROR_ENABLED == 'true'
106106
steps:
107-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
107+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
108108
with:
109109
fetch-depth: 0
110110

111-
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
111+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
112112
with:
113113
ssh-private-key: ${{ secrets.GITEA_SSH_KEY }}
114114

@@ -122,14 +122,20 @@ jobs:
122122
runs-on: ubuntu-latest
123123
if: vars.RADICLE_MIRROR_ENABLED == 'true'
124124
steps:
125-
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4
125+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
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

0 commit comments

Comments
 (0)