Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 77 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
test:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
if: vars.RUN_EXTENSION_CI == 'true'

strategy:
Expand Down Expand Up @@ -69,6 +70,7 @@ jobs:
security:
name: Security Audit
runs-on: ubuntu-latest
timeout-minutes: 15
if: vars.RUN_EXTENSION_CI == 'true'

steps:
Expand Down Expand Up @@ -100,41 +102,88 @@ jobs:
rsr-compliance:
name: RSR Compliance Check
runs-on: ubuntu-latest

timeout-minutes: 10

# NON-NORMATIVE MIRROR of the RSR v2.0 criteria SSOT
# (hyperpolymath/standards 0-canon/rsr/rsr-criteria-v2.a2ml; the ONE
# normative checker is hypatia:rsr-conformance). Regenerate this step
# from the SSOT detector table instead of hand-drifting it.
#
# Owner ruling 2026-10-10 (#78): community-health files stay AsciiDoc
# (SECURITY.adoc, CODE_OF_CONDUCT.adoc, CONTRIBUTING.adoc). The SSOT's
# 2.1.3/2.1.4/2.1.5 detectors list only .md variants; that detector lag
# is reported upstream (standards#994) — GitHub community-profile
# recognition of .adoc is requested in github/orgs/community discussions
# #181843 and #189645. The .md variants are still ACCEPTED here so a
# future conversion cannot fail this check.
#
# .well-known: canonical location is www/.well-known/ (rsr-template-repo#53,
# stage-5 sweep); a legacy root .well-known/ is tolerated with a warning
# during the migration window.
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Check required files
run: |
echo "Checking RSR Bronze compliance..."

# Documentation
test -f README.md || test -f README.adoc || (echo "Missing README.md or README.adoc" && exit 1)
test -f CONTRIBUTING.adoc || (echo "Missing CONTRIBUTING.adoc" && exit 1)
test -f CODE_OF_CONDUCT.md || (echo "Missing CODE_OF_CONDUCT.md" && exit 1)
test -f SECURITY.md || (echo "Missing SECURITY.md" && exit 1)
test -f MAINTAINERS.adoc || (echo "Missing MAINTAINERS.adoc" && exit 1)
test -f CHANGELOG.adoc || (echo "Missing CHANGELOG.adoc" && exit 1)
test -f CLAUDE.md || (echo "Missing CLAUDE.md" && exit 1)

# Licenses
test -f LICENSES/MPL-2.0.txt || (echo "Missing LICENSES/MPL-2.0.txt" && exit 1)
test -f LICENSES/CC-BY-SA-4.0.txt || (echo "Missing LICENSES/CC-BY-SA-4.0.txt" && exit 1)

# .well-known/
test -f .well-known/security.txt || (echo "Missing security.txt" && exit 1)
test -f .well-known/ai.txt || (echo "Missing ai.txt" && exit 1)
test -f .well-known/humans.txt || (echo "Missing humans.txt" && exit 1)

# Build system
test -f justfile || test -f Justfile || (echo "Missing justfile or Justfile" && exit 1)

echo "✅ RSR Bronze compliance verified!"
set -u
echo "Checking RSR compliance (mirror of rsr-criteria-v2 detectors)..."
FAIL=0
req() { # req <criterion> <description> <candidate...>
crit="$1"; desc="$2"; shift 2
for f in "$@"; do [ -f "$f" ] && { echo " ✅ $crit $desc ($f)"; return 0; }
[ -d "$f" ] && { echo " ✅ $crit $desc ($f/)"; return 0; }; done
echo " ❌ $crit missing $desc (looked for: $*)"; FAIL=1
}
# 2.1.x documentation
req 2.1.1 README README.adoc README.md
req 2.1.5 CONTRIBUTING CONTRIBUTING.adoc .github/CONTRIBUTING.md CONTRIBUTING.md
req 2.1.4 CODE_OF_CONDUCT CODE_OF_CONDUCT.adoc .github/CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md
req 2.1.3 SECURITY SECURITY.adoc .github/SECURITY.md SECURITY.md
req 2.1.7 MAINTAINERS MAINTAINERS.adoc docs/MAINTAINERS.adoc
req 2.1.6 CHANGELOG CHANGELOG.adoc CHANGELOG.md
req 2.1.8 GOVERNANCE GOVERNANCE.adoc docs/GOVERNANCE.adoc .github/GOVERNANCE.md
req — CLAUDE.md CLAUDE.md
# 2.1.2 / 7.1.2 licensing
req 2.1.2 LICENSE LICENSE
req 7.1.2 LICENSES/MPL-2.0.txt LICENSES/MPL-2.0.txt
req 7.1.2 LICENSES/CC-BY-SA-4.0.txt LICENSES/CC-BY-SA-4.0.txt
# 2.3.1 AI manifest front door
req 2.3.1 AI-manifest 0-AI-MANIFEST.a2ml 0-AI-MANIFEST.deed
# 1.1.2 / 1.1.3 build system: Justfile present, Makefile banned
req 1.1.2 Justfile Justfile justfile
if [ -f Makefile ] || [ -f makefile ]; then
echo " ❌ 1.1.3 Makefile present — estate policy is Justfile"; FAIL=1
else
echo " ✅ 1.1.3 no Makefile"
fi
# 3.1.1 descriptiles canonical, 6a2 retired
req 3.1.1 descriptiles .machine_readable/descriptiles
if [ -d .machine_readable/6a2 ]; then
echo " ❌ 3.1.1 retired .machine_readable/6a2/ still present"; FAIL=1
else
echo " ✅ 3.1.1 no retired 6a2/"
fi
# 2.2.1 well-known — canonical www/, legacy root tolerated with warning
for f in security.txt ai.txt humans.txt; do
if [ -f "www/.well-known/$f" ]; then
echo " ✅ 2.2.1 www/.well-known/$f"
elif [ -f ".well-known/$f" ]; then
echo " ⚠️ 2.2.1 legacy root .well-known/$f — canonical is www/.well-known/ (rsr-template-repo#53)"
else
echo " ❌ 2.2.1 missing $f (want www/.well-known/$f)"; FAIL=1
fi
done
if [ "$FAIL" -ne 0 ]; then
echo "::error::RSR compliance check failed — see ❌ rows above"
exit 1
fi
echo "✅ RSR compliance verified (non-normative mirror; oracle: hypatia:rsr-conformance)"

build:
name: Build Extension
runs-on: ubuntu-latest
timeout-minutes: 30
if: vars.RUN_EXTENSION_CI == 'true'
needs: [test, security, rsr-compliance]

Expand Down Expand Up @@ -173,6 +222,7 @@ jobs:
performance:
name: Performance Benchmarks
runs-on: ubuntu-latest
timeout-minutes: 30
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.RUN_EXTENSION_CI == 'true'

steps:
Expand Down Expand Up @@ -200,6 +250,7 @@ jobs:
docs:
name: Build Documentation
runs-on: ubuntu-latest
timeout-minutes: 15
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

steps:
Expand All @@ -219,6 +270,7 @@ jobs:
release:
name: Create Release
runs-on: ubuntu-latest
timeout-minutes: 45
if: startsWith(github.ref, 'refs/tags/v') && vars.RUN_EXTENSION_CI == 'true'
needs: [build]
permissions:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: 30
permissions:
# required for all workflows
security-events: write
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/guix-nix-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ permissions:
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Enforce Guix primary / Nix fallback
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/hypatia-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-License-Identifier: MPL-2.0
#
# Standalone Hypatia security scan (push / PR / weekly). This is NOT a duplicate
# of the `hypatia-scan` job in `static-analysis-gate.yml`: that job exists to
# feed the gitbot-fleet LEARNING pipeline (via `deposit-findings`), whereas this
# workflow is the repo's independent security scan. Same tool, two consumers.
# Required by the estate baseline (Hypatia workflow_audit/missing_workflow;
# RSR v2.0 SSOT criterion 6.1.2) and by rsr-template-repo's canonical set.
#
# The reusable workflow pins the scanner to a vetted Hypatia commit, validates
# findings, uploads SARIF to the Security tab, and runs ADVISORY (fix-forward)
# until this repo commits a `.hypatia-baseline.json` + `scripts/apply-baseline.sh`,
# which arms the blocking gate automatically (standards#399/#437 mechanism).
name: Hypatia Security Scan

on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master]
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: read # required by the reusable workflow (staleness check reads workflow runs)
contents: read
security-events: write

jobs:
hypatia:
uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@10e0b6ffb979f0a27fe58206512055133e67460a
14 changes: 13 additions & 1 deletion .github/workflows/instant-sync.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# SPDX-License-Identifier: MPL-2.0
# Instant Forge Sync - Triggers propagation to all forges on push/release
#
# WF017 gate: the dispatch step consumes `secrets.FARM_DISPATCH_TOKEN`. On
# repos where that secret has not been propagated the ungated action fails
# EVERY run (the 2026-05-30 estate audit caught 65 repos this way), so the
# job binds a presence boolean and the step gates on it — the idiom the
# Hypatia rule recognises (env-boolean gate).
name: Instant Sync

on:
Expand All @@ -14,9 +20,13 @@ permissions:
jobs:
dispatch:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
HAS_FARM_TOKEN: ${{ secrets.FARM_DISPATCH_TOKEN != '' }}
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
steps:
- name: Trigger Propagation
id: dispatch
if: env.HAS_FARM_TOKEN == 'true'
continue-on-error: true
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
Expand All @@ -34,7 +44,9 @@ jobs:
- name: Confirm
if: always()
run: |
if [ "${{ steps.dispatch.outcome }}" = "failure" ]; then
if [ "${{ env.HAS_FARM_TOKEN }}" != "true" ]; then
echo "::notice::FARM_DISPATCH_TOKEN not set on this repository — forge propagation skipped."
elif [ "${{ steps.dispatch.outcome }}" = "failure" ]; then
echo "::warning::Propagation dispatch failed; rotate FARM_DISPATCH_TOKEN for hyperpolymath/.git-private-farm."
else
echo "::notice::Propagation triggered for ${{ github.event.repository.name }}"
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/rsr-antipattern.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: MPL-2.0

Check warning on line 1 in .github/workflows/rsr-antipattern.yml

View workflow job for this annotation

GitHub Actions / Hypatia neurosymbolic scan

[hypatia] Job `antipattern-check` in rsr-antipattern.yml has no `timeout-minutes:` declaration. Default is 6 hours — a stuck codeload fetch or runner hang can burn budget. Add `timeout-minutes: 10` (or proportional).
# RSR Anti-Pattern CI Check
# SPDX-License-Identifier: MPL-2.0
#
Expand Down Expand Up @@ -84,7 +84,12 @@
if claude_md.exists():
in_table = False
for line in claude_md.read_text(encoding='utf-8').splitlines():
if re.search(r'TypeScript [Ee]xemptions', line):
# Intended heading: "### TypeScript Exemptions" in .claude/CLAUDE.md.
# Anchored to the markdown heading shape so a PROSE mention of the
# phrase cannot silently walk the parser into the wrong section
# (Hypatia WF022 — the affinescript silent-gate failure class,
# standards#183).
if re.search(r'^#{1,4}\s+.*TypeScript [Ee]xemptions', line):
in_table = True
continue
if in_table and line.startswith(('### ', '## ', '# ')):
Expand Down Expand Up @@ -144,7 +149,7 @@
fi
echo "✅ No Go files"

- name: Check for Python (non-SaltStack)

Check warning on line 152 in .github/workflows/rsr-antipattern.yml

View workflow job for this annotation

GitHub Actions / Hypatia neurosymbolic scan

[hypatia] workflow .github/workflows/rsr-antipattern.yml:152 step `Check for Python (non-SaltStack)` swallows non-zero exit via `|| true` — failures will be masked
run: |
PY_FILES=$(find . -name "*.py" | grep -v salt | grep -v _states | grep -v _modules | grep -v pillar | grep -v venv | grep -v __pycache__ || true)
if [ -n "$PY_FILES" ]; then
Expand Down
69 changes: 54 additions & 15 deletions .github/workflows/wellknown-enforcement.yml
Original file line number Diff line number Diff line change
@@ -1,48 +1,74 @@
# SPDX-License-Identifier: MPL-2.0
# Well-Known Standards (RFC 9116 + RSR)
#
# Canonical location for the .well-known bundle is www/.well-known/
# (rsr-template-repo#53, stage-5 sweep #119; the template's
# dot-wellknown-enforcement.yml semantics). A repository-root .well-known/
# is LEGACY — tolerated with a warning during the migration window, never
# silently validated as canonical. A security.txt absent from BOTH
# locations is a HARD ERROR (the pre-2026-10 version of this workflow
# exit-0'd there — a vacuous gate; see the defect class PR #67 eliminated).
name: Well-Known Standards (RFC 9116 + RSR)
on:
push:
branches: [main, master]
paths:
- '.well-known/**'
- 'www/.well-known/**'
- '.well-known/**' # legacy location — migration window
- 'security.txt'
pull_request:
paths:
- 'www/.well-known/**'
- '.well-known/**'
- 'security.txt'
schedule:
# Weekly expiry check
# Weekly expiry check (Mondays 09:00 UTC)
- cron: '0 9 * * 1'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: RFC 9116 security.txt validation
run: |
SECTXT=""
[ -f ".well-known/security.txt" ] && SECTXT=".well-known/security.txt"
[ -f "security.txt" ] && SECTXT="security.txt"

if [ -f "www/.well-known/security.txt" ]; then
SECTXT="www/.well-known/security.txt"
elif [ -f ".well-known/security.txt" ]; then
SECTXT=".well-known/security.txt"
echo "::warning::security.txt at legacy root .well-known/ — canonical location is www/.well-known/ (rsr-template-repo#53)"
elif [ -f "security.txt" ]; then
SECTXT="security.txt"
echo "::warning::security.txt at repository root — canonical location is www/.well-known/"
fi

if [ -z "$SECTXT" ]; then
echo "::warning::No security.txt found. See https://github.com/hyperpolymath/well-known-ecosystem"
exit 0
echo "::error::No security.txt found — required by RFC 9116 / RSR 2.2.1. See https://github.com/hyperpolymath/well-known-ecosystem"
exit 1
fi

# Required: Contact
grep -q "^Contact:" "$SECTXT" || { echo "::error::Missing Contact field"; exit 1; }

# Required: Expires
if ! grep -q "^Expires:" "$SECTXT"; then
echo "::error::Missing Expires field"
exit 1
fi

# Check expiry
EXPIRES=$(grep "^Expires:" "$SECTXT" | cut -d: -f2- | tr -d ' ' | head -1)
if date -d "$EXPIRES" > /dev/null 2>&1; then
Expand All @@ -60,18 +86,31 @@
- name: RSR well-known compliance
run: |
MISSING=""
[ ! -f ".well-known/security.txt" ] && [ ! -f "security.txt" ] && MISSING="$MISSING security.txt"
[ ! -f ".well-known/ai.txt" ] && MISSING="$MISSING ai.txt"
[ ! -f ".well-known/humans.txt" ] && MISSING="$MISSING humans.txt"

LEGACY=""
for f in security.txt ai.txt humans.txt; do
if [ -f "www/.well-known/$f" ]; then
:
elif [ -f ".well-known/$f" ] || { [ "$f" = security.txt ] && [ -f security.txt ]; }; then
LEGACY="$LEGACY $f"
else
MISSING="$MISSING $f"
fi
done
if [ -n "$LEGACY" ]; then
echo "::warning::legacy .well-known location (canonical is www/.well-known/):$LEGACY — see rsr-template-repo scripts/migrate-wellknown-to-www.sh"
fi

if [ -n "$MISSING" ]; then
echo "::warning::Missing RSR recommended files:$MISSING"
echo "Reference: https://github.com/hyperpolymath/well-known-ecosystem/.well-known/"
else
echo "✅ RSR well-known compliant"
fi

- name: Canonical well-known bundle validation
run: bash www/tests/check-wellknown.sh

- name: Mixed content check

Check warning on line 113 in .github/workflows/wellknown-enforcement.yml

View workflow job for this annotation

GitHub Actions / Hypatia neurosymbolic scan

[hypatia] workflow .github/workflows/wellknown-enforcement.yml:113 step `Mixed content check` swallows non-zero exit via `|| true` — failures will be masked
run: |
MIXED=$(grep -rE 'src="http://|href="http://' --include="*.html" --include="*.htm" . 2>/dev/null | grep -vE 'localhost|127\.0\.0\.1|example\.com' | head -5 || true)
if [ -n "$MIXED" ]; then
Expand Down
Loading
Loading