diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/bug_report.md b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 987aab6bc..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: "[Bug]: "
-labels: 'bug, priority: unset, triage'
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Desktop (please complete the following information):**
- - OS: [e.g. iOS]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
-
-**Smartphone (please complete the following information):**
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS8.1]
- - Browser [e.g. stock browser, safari]
- - Version [e.g. 22]
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/custom.md b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/custom.md
deleted file mode 100644
index 48d5f81fa..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/custom.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: Custom issue template
-about: Describe this issue template's purpose here.
-title: ''
-labels: ''
-assignees: ''
-
----
-
-
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/documentation.md b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/documentation.md
deleted file mode 100644
index 4fcb9f9fa..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/documentation.md
+++ /dev/null
@@ -1,66 +0,0 @@
----
-name: Documentation
-about: Report unclear, missing, or incorrect documentation
-title: "[DOCS]: "
-labels: 'documentation, priority: unset, triage'
-assignees: ''
-
----
-
-name: Documentation
-description: Report unclear, missing, or incorrect documentation
-title: "[Docs]: "
-labels: ["documentation", "triage"]
-body:
- - type: markdown
- attributes:
- value: |
- Help us improve our documentation by reporting issues or gaps.
-
- - type: dropdown
- id: type
- attributes:
- label: Documentation issue type
- options:
- - Missing (documentation doesn't exist)
- - Incorrect (information is wrong)
- - Unclear (confusing or hard to follow)
- - Outdated (no longer accurate)
- - Typo or grammar
- validations:
- required: true
-
- - type: input
- id: location
- attributes:
- label: Location
- description: Where is this documentation? (URL, file path, or section name)
- placeholder: README.adoc, section "Installation"
- validations:
- required: true
-
- - type: textarea
- id: description
- attributes:
- label: Description
- description: What's the problem with the current documentation?
- placeholder: Describe what's wrong or missing
- validations:
- required: true
-
- - type: textarea
- id: suggestion
- attributes:
- label: Suggested improvement
- description: How should it be fixed or improved?
- placeholder: The documentation should say...
- validations:
- required: false
-
- - type: checkboxes
- id: contribution
- attributes:
- label: Contribution
- options:
- - label: I would be willing to submit a PR to fix this
- required: false
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/feature_request.md b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 3e8fa7e7e..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: 'enhancement, priority: unset, triage'
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/question.md b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index fd0e2a5cc..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-name: Question
-about: Ask a question about usage or behaviour
-title: "[QUESTION]: "
-labels: question, triage
-assignees: ''
-
----
-
-name: Question
-description: Ask a question about usage or behaviour
-title: "[Question]: "
-labels: ["question", "triage"]
-body:
- - type: markdown
- attributes:
- value: |
- Have a question? You can also ask in [Discussions](../discussions) for broader conversations.
-
- - type: textarea
- id: question
- attributes:
- label: Your question
- description: What would you like to know?
- placeholder: How do I...?
- validations:
- required: true
-
- - type: textarea
- id: context
- attributes:
- label: Context
- description: Any relevant context that helps us answer your question
- placeholder: I'm trying to achieve X and I've tried Y...
- validations:
- required: false
-
- - type: textarea
- id: research
- attributes:
- label: What I've already tried
- description: What have you already looked at or attempted?
- placeholder: I've read the README and searched issues but...
- validations:
- required: false
-
- - type: checkboxes
- id: checked
- attributes:
- label: Pre-submission checklist
- options:
- - label: I have searched existing issues and discussions
- required: true
- - label: I have read the documentation
- required: true
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/codeql.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/codeql.yml
index 90f0622bb..153ea84fb 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/codeql.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/codeql.yml
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
name: CodeQL Security Analysis
on:
@@ -7,21 +8,43 @@ on:
pull_request:
branches: [main, master]
schedule:
- - cron: '0 6 * * 1'
+ - cron: '0 6 1 * *' # monthly 1st 06:00 UTC
+# Estate guardrail: cancel superseded runs so re-pushes / rebased PR
+# updates do not pile up queued runs against the shared account-wide
+# Actions concurrency pool. Applied only to read-only check workflows
+# (no publish/mutation), so cancelling a superseded run is always safe.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: false
+ cancel-in-progress: true
permissions:
+ actions: read
contents: read
jobs:
- analyze-js:
+ analyze:
+ runs-on: ubuntu-latest
permissions:
- actions: read
contents: read
security-events: write
- uses: hyperpolymath/standards/.github/workflows/codeql-reusable.yml@210f14e753c80064ec1bcae72f1d654dd9b0e687
- with:
- language: javascript-typescript
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build-mode: none
+ steps:
+ - name: Checkout
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v3
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v3
+ with:
+ category: "/language:${{ matrix.language }}"
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/comprehensive-quality.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/comprehensive-quality.yml
deleted file mode 100644
index 2ff46e993..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/comprehensive-quality.yml
+++ /dev/null
@@ -1,226 +0,0 @@
-# SPDX-License-Identifier: MPL-2.0
-name: Comprehensive Quality Gates
-
-on:
- push:
- branches: [main, master]
- pull_request:
- schedule:
- - cron: '0 5 * * *'
-
-permissions: read-all
-
-jobs:
- # DEPENDABILITY - Stability and reliability
- dependability:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check test coverage
- run: |
- echo "Checking for test files..."
- TESTS=$(find . -name "*_test.*" -o -name "test_*" -o -name "*_spec.*" -o -name "*.test.*" | wc -l)
- echo "Found $TESTS test files"
- if [ "$TESTS" -lt 1 ]; then
- echo "::warning::No test files detected"
- fi
- - name: Check error handling
- run: |
- # Check for proper error handling patterns
- PANICS=$(grep -rE "panic!|unwrap\(\)|expect\(" --include="*.rs" . 2>/dev/null | wc -l || echo "0")
- echo "Rust panics/unwraps: $PANICS"
-
- # SECURITY - Multi-layer security scanning
- security:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Secret scanning
- uses: trufflesecurity/trufflehog@8a8ef8526528d8a4ff3e2c90be08e25ef8efbd9b # v3.88.3
- continue-on-error: true
- - name: Dependency vulnerabilities
- run: |
- if [ -f "Cargo.toml" ]; then
- cargo install cargo-audit && cargo audit || true
- fi
- if [ -f "requirements.txt" ]; then
- pip install safety && safety check -r requirements.txt || true
- fi
- - name: SAST scan
- uses: returntocorp/semgrep-action@v1
- continue-on-error: true
-
- # INTEROPERABILITY - API and format compatibility
- interoperability:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check API specs
- run: |
- if [ -f "openapi.yaml" ] || [ -f "openapi.json" ]; then
- echo "✅ OpenAPI spec found"
- fi
- if [ -f "schema.graphql" ]; then
- echo "✅ GraphQL schema found"
- fi
- - name: Validate JSON/YAML schemas
- run: |
- find . -name "*.json" -exec python3 -m json.tool {} \; 2>/dev/null | head -5 || true
-
- # VALIDATION - Input/output validation
- validation:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check for validation patterns
- run: |
- VALIDATION=$(grep -rE "validate|sanitize|Schema|Validator" --include="*.rs" --include="*.res" --include="*.ex" . 2>/dev/null | wc -l || echo "0")
- echo "Validation patterns found: $VALIDATION"
-
- # ATTESTATION - Supply chain integrity (SLSA)
- attestation:
- runs-on: ubuntu-latest
- timeout-minutes: 30
- permissions:
- id-token: write
- contents: read
- attestations: write
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Generate SBOM
- run: |
- echo "SBOM generation would run here"
- # For Rust: cargo-sbom
- # For Node: npm sbom
- - name: Check signatures
- run: |
- if [ -f "CHECKSUMS.txt" ] || [ -f "SHA256SUMS" ]; then
- echo "✅ Checksums file present"
- fi
-
- # VERIFICATION - Formal methods where applicable
- verification:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check SPARK proofs
- run: |
- if find . -name "*.ads" | grep -q .; then
- echo "Ada/SPARK files found - formal verification applicable"
- fi
- - name: Type coverage
- run: |
- if [ -f "rescript.json" ]; then
- echo "ReScript provides 100% type coverage"
- fi
-
- # FUNCTIONALITY - Feature completeness
- functionality:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check TODOs and FIXMEs
- run: |
- echo "=== Incomplete items ==="
- grep -rn "TODO\|FIXME\|UNIMPLEMENTED\|unimplemented!" . 2>/dev/null | head -20 || echo "None"
- - name: Check deprecated usage
- run: |
- grep -rn "deprecated\|DEPRECATED" . 2>/dev/null | head -10 || echo "No deprecations"
-
- # PERFORMANCE - Benchmarks and profiling
- performance:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check for benchmarks
- run: |
- BENCHES=$(find . -name "*bench*" -o -name "*perf*" | wc -l)
- echo "Benchmark files: $BENCHES"
- - name: Binary size check (Rust)
- run: |
- if [ -f "Cargo.toml" ]; then
- cargo build --release 2>/dev/null || true
- find target/release -maxdepth 1 -type f -executable -exec ls -lh {} \; 2>/dev/null || true
- fi
-
- # ACCESSIBILITY - A11y compliance
- accessibility:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- if: hashFiles('**/*.html') != ''
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: HTML accessibility check
- run: |
- echo "Checking for a11y attributes..."
- A11Y=$(grep -rE 'aria-|role=|alt=' --include="*.html" . 2>/dev/null | wc -l || echo "0")
- echo "A11y attributes found: $A11Y"
- - name: Lighthouse (if web project)
- run: |
- echo "Lighthouse would run on deployed URL"
-
- # LICENSE COMPLIANCE
- license:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check license files
- run: |
- if [ -f "LICENSE" ] || [ -f "LICENSE.txt" ] || [ -f "LICENSE.md" ]; then
- echo "✅ License file present"
- head -5 LICENSE* 2>/dev/null
- else
- echo "::warning::No LICENSE file"
- fi
- - name: Check SPDX headers
- run: |
- SPDX=$(grep -rE "SPDX-License-Identifier" . 2>/dev/null | wc -l || echo "0")
- echo "Files with SPDX headers: $SPDX"
-
- # DOCUMENTATION QUALITY
- documentation:
- runs-on: ubuntu-latest
- timeout-minutes: 20
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - name: Check docs completeness
- run: |
- DOCS=""
- [ -f "README.md" ] || [ -f "README.adoc" ] && DOCS="$DOCS README"
- [ -f "CONTRIBUTING.md" ] || [ -f "3-practice/CONTRIBUTING.adoc" ] && DOCS="$DOCS CONTRIBUTING"
- [ -f "CHANGELOG.md" ] && DOCS="$DOCS CHANGELOG"
- [ -f "3-practice/SECURITY.md" ] && DOCS="$DOCS SECURITY"
- [ -d "docs" ] && DOCS="$DOCS docs/"
- echo "Documentation:$DOCS"
- - name: Check code comments
- run: |
- COMMENTS=$(grep -rE "^[[:space:]]*(//|#|/\*)" --include="*.rs" --include="*.res" --include="*.py" . 2>/dev/null | wc -l || echo "0")
- echo "Comment lines: $COMMENTS"
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/generator-generic-ossf-slsa3-publish.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/generator-generic-ossf-slsa3-publish.yml
index 2ca650b13..9d2b42fff 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/generator-generic-ossf-slsa3-publish.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/generator-generic-ossf-slsa3-publish.yml
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
@@ -18,19 +19,20 @@ on:
release:
types: [created]
-permissions: read-all
+permissions:
+ actions: read
+ contents: read
jobs:
build:
runs-on: ubuntu-latest
- timeout-minutes: 30
permissions:
contents: read
outputs:
digests: ${{ steps.hash.outputs.digests }}
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# ========================================================
#
@@ -67,7 +69,7 @@ jobs:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
base64-subjects: "${{ needs.build.outputs.digests }}"
upload-assets: true # Optional: Upload to a new release
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/governance.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/governance.yml
index ff72fbc89..2b54ed7fa 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/governance.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/governance.yml
@@ -1,30 +1,17 @@
# SPDX-License-Identifier: MPL-2.0
-# governance.yml — single wrapper calling the shared estate governance bundle
-# in hyperpolymath/standards instead of carrying per-repo copies.
-#
-# Replaces the per-repo governance scaffolding removed in the same commit:
-# quality.yml, guix-nix-policy.yml, npm-bun-blocker.yml, ts-blocker.yml,
-# security-policy.yml, rsr-antipattern.yml, wellknown-enforcement.yml,
-# workflow-linter.yml
-#
-# Load-bearing build/security workflows stay standalone in the repo
-# (rust-ci, codeql, dependabot, release, scan/mirror/pages plumbing).
-
+# This workflow is managed by gh actions-lock.
name: Governance
on:
push:
branches: [main, master]
pull_request:
+ branches: [main, master]
workflow_dispatch:
permissions:
- actions: read
contents: read
jobs:
governance:
- permissions:
- actions: read
- contents: read
- uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@210f14e753c80064ec1bcae72f1d654dd9b0e687
+ uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/haskell.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/haskell.yml
index 5005ae83b..88eeea42e 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/haskell.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/haskell.yml
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
name: Haskell CI
on:
@@ -7,24 +8,25 @@ on:
pull_request:
branches: [ "main" ]
-permissions: read-all
+permissions:
+ actions: read
+ contents: read
jobs:
build:
runs-on: ubuntu-latest
- timeout-minutes: 30
permissions:
contents: read
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-haskell@28c8ff1d6cbeaed15ce310b1952dc19352a0a07d # v1.1.5
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: haskell-actions/setup@0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d # v2.12.1
with:
- ghc-version: '8.10.3'
- cabal-version: '3.2'
+ ghc-version: '9.8.2'
+ cabal-version: '3.10'
- name: Cache
- uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
env:
cache-name: cache-cabal
with:
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/mirror.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/mirror.yml
index d5201b962..ca54d84f4 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/mirror.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/mirror.yml
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
name: Mirror to Git Forges
on:
@@ -7,12 +8,10 @@ on:
workflow_dispatch:
permissions:
+ actions: read
contents: read
jobs:
mirror:
- permissions:
- actions: read
- contents: read
- uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@210f14e753c80064ec1bcae72f1d654dd9b0e687
+ uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c
secrets: inherit
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/php-security.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/php-security.yml
index 541d31721..bc70f2f54 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/php-security.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/php-security.yml
@@ -1,18 +1,29 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
name: PHP Security Check
-on: [push, pull_request]
+on:
+ push:
+ branches: [main, master]
+ pull_request:
-permissions: read-all
+# Estate guardrail: scope push to default branches so a PR fires once (not
+# push+PR), and cancel superseded runs. Safe — read-only PR-triggered check.
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ actions: read
+ contents: read
jobs:
security:
runs-on: ubuntu-latest
- timeout-minutes: 20
permissions:
contents: read
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: PHP Security Scan
run: |
# Check for dangerous functions
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/scorecard.yml b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/scorecard.yml
index 0b978aa38..23f4a3ff4 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/scorecard.yml
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.github/workflows/scorecard.yml
@@ -1,19 +1,20 @@
# SPDX-License-Identifier: MPL-2.0
+# This workflow is managed by gh actions-lock.
name: OSSF Scorecard
on:
- push:
- branches: [main, master]
schedule:
- - cron: '0 4 * * 0'
+ - cron: '0 4 * * *'
workflow_dispatch:
-permissions: read-all
-
+permissions:
+ contents: read
+ security-events: write
+ id-token: write
jobs:
- analysis:
+ scorecard:
+ uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c
permissions:
contents: read
security-events: write
- uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@210f14e753c80064ec1bcae72f1d654dd9b0e687
- secrets: inherit
+ id-token: write
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.gitignore b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.gitignore
index 45f10b185..79fa485f6 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.gitignore
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/.gitignore
@@ -54,6 +54,8 @@ __pycache__/
# Haskell
/.stack-work/
/dist-newstyle/
+/cabal/
+.cache/
# Chapel
*.chpl.tmp.*
@@ -77,3 +79,10 @@ htmlcov/
/tmp/
*.tmp
*.bak
+target/
+node_modules/
+_build/
+deps/
+.elixir_ls/
+build/
+dist/
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE
new file mode 100644
index 000000000..14e2f777f
--- /dev/null
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE.txt b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE.txt
deleted file mode 100644
index 6c758aad9..000000000
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/LICENSE.txt
+++ /dev/null
@@ -1,91 +0,0 @@
-SPDX-License-Identifier: MPL-2.0
-SPDX-FileCopyrightText: 2024-2025 hyperpolymath
-
-================================================================================
-DUAL LICENSE: MIT OR PMPL-1.0-or-later
-================================================================================
-
-This project is dual-licensed under the MIT License OR the GNU Affero General
-Public License v3.0 or later. You may choose to use, copy, modify, and
-distribute this work under the terms of EITHER license (your choice).
-
---------------------------------------------------------------------------------
-MIT LICENSE
---------------------------------------------------------------------------------
-
-Copyright (c) 2024-2025 hyperpolymath
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
---------------------------------------------------------------------------------
-GNU AFFERO GENERAL PUBLIC LICENSE v3.0 OR LATER
---------------------------------------------------------------------------------
-
-This program is free software: you can redistribute it and/or modify it under
-the terms of the GNU Affero General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-details.
-
-You should have received a copy of the GNU Affero General Public License along
-with this program. If not, see .
-
-The full text of the AGPL-3.0 is available at:
- https://www.gnu.org/licenses/agpl-3.0.txt
-
---------------------------------------------------------------------------------
-CHOOSING YOUR LICENSE
---------------------------------------------------------------------------------
-
-You may choose to use this work under:
- 1. MIT License - Standard permissive open source license
- 2. PMPL-1.0-or-later - Copyleft license requiring source disclosure for
- network services
-
-For most uses, MIT License provides maximum flexibility.
-For ensuring open source remains open (especially for SaaS/network services),
-PMPL-1.0-or-later provides stronger protections.
-
-================================================================================
-PALIMPSEST PHILOSOPHICAL OVERLAY (NON-BINDING)
-================================================================================
-
-This project encourages (but does not legally require) adherence to the
-principles of the Palimpsest License - a framework for consent-based digital
-interaction and the future web.
-
-Core Principles (Encouraged):
- - Respect for emotional and creative lineage
- - Transparent AI training practices with explicit consent
- - Preservation of metadata and attribution
- - Protection of narrative intent and cultural context
-
-The Palimpsest principles represent our vision for a consent-based internet.
-While not legally binding for use of this software, we encourage all users
-and contributors to familiarize themselves with these principles.
-
-Learn more: https://github.com/hyperpolymath/palimpsest-license
-
-================================================================================
-END OF LICENSE
-================================================================================
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/README.adoc b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/README.adoc
index 8745882ad..c9a00a7ae 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/README.adoc
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/README.adoc
@@ -1,4 +1,12 @@
+// SPDX-License-Identifier: MPL-2.0
+// SPDX-License-Identifier: CC-BY-SA-4.0
+
= Sanctify-PHP
+
+image:https://img.shields.io/badge/License-MPL--2.0-blue.svg[License: MPL-2.0,link="https://www.mozilla.org/MPL/2.0/"]
+image:https://img.shields.io/badge/Philosophy-Palimpsest-indigo.svg[Palimpsest,link="https://github.com/hyperpolymath/palimpsest-license"]
+
+
:author: Jonathan D.A. Jewell
:email: j.d.a.jewell@open.ac.uk
:toc:
@@ -6,6 +14,14 @@
Haskell-based PHP hardening and security analysis tool.
+== Current Status
+
+Sanctify-PHP already contains substantial parser, analysis, transform, and reporting code, but it should still be treated as a research or beta security tool.
+
+* The implementation breadth is ahead of the verification depth.
+* The most important remaining gaps are taint-analysis tests, end-to-end execution coverage, and proof obligations for the security-analysis core.
+* Use link:ROADMAP.adoc[ROADMAP.adoc], link:TEST-NEEDS.md[TEST-NEEDS.md], and link:PROOF-NEEDS.md[PROOF-NEEDS.md] as the primary readiness documents.
+
== Overview
Sanctify-PHP transforms PHP code to be safer and more robust:
@@ -18,6 +34,11 @@ Sanctify-PHP transforms PHP code to be safer and more robust:
* Generates reports in JSON/SARIF/HTML formats
* Exports infrastructure recommendations (php.ini, nginx, Guix)
+[NOTE]
+====
+This README describes the intended capability surface of the tool. It should not be read as proof that every analysis and transform is already trustworthy enough for production security decisions.
+====
+
== Installation
[source,bash]
@@ -30,7 +51,7 @@ cabal install
nix build
# Using Guix
-guix build -f guix.scm
+guix build -f build/guix.scm
----
== Usage
@@ -147,3 +168,8 @@ PMPL-1.0-or-later
* https://github.com/hyperpolymath/aegis[aegis] - Container orchestrator
* https://github.com/hyperpolymath/wordpress-wharf[wordpress-wharf] - WordPress deployment
* https://github.com/hyperpolymath/wp-audit-toolkit[wp-audit-toolkit] - WordPress auditing
+
+
+== Architecture
+
+See link:TOPOLOGY.md[TOPOLOGY.md] for a visual architecture map and completion dashboard.
diff --git a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/app/Main.hs b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/app/Main.hs
index 01f9711f9..8da24706d 100644
--- a/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/app/Main.hs
+++ b/rhodium-standard-repositories/satellites/cccp/satellites/sanctify-php/app/Main.hs
@@ -4,43 +4,161 @@ module Main where
import System.Environment (getArgs)
import System.Exit (exitFailure, exitSuccess)
+import System.IO (hFlush, stdout, hPutStrLn, stderr)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
-import System.Directory (doesFileExist, doesDirectoryExist, listDirectory)
+import qualified Data.ByteString.Lazy.Char8 as BL8
+import System.Directory (doesFileExist, doesDirectoryExist, listDirectory, getModificationTime)
import System.FilePath ((>), takeExtension)
-import Control.Monad (forM, filterM, when)
+import Control.Monad (forM, forM_, filterM, when, unless, forever)
+import Control.Concurrent (threadDelay)
import Data.Either (partitionEithers)
+import Data.List (isPrefixOf, isSuffixOf)
+import Data.Maybe (isJust, fromMaybe, catMaybes)
+import Data.Time.Clock (UTCTime)
+import qualified Data.Map.Strict as Map
import Sanctify.Parser
import Sanctify.AST
import Sanctify.Analysis.Security
-import Sanctify.Analysis.Types
+import Sanctify.Analysis.Types (emptyTypeContext)
import Sanctify.WordPress.Constraints
import Sanctify.Transform.StrictTypes
import Sanctify.Transform.Sanitize
import Sanctify.Transform.TypeHints
-import Sanctify.Emit
+import Sanctify.Emit (emitPhp, emitPhpIniRecommendations, emitNginxRules, emitGuixOverrides)
import Sanctify.Config
-import Sanctify.Report
+import qualified Sanctify.Report as SReport
+
+-- | CLI options
+data Options = Options
+ { optCommand :: Command
+ , optInteractive :: Bool
+ , optWatch :: Bool
+ , optFormat :: OutputFormat
+ , optSeverity :: [Severity]
+ , optTypes :: [Text]
+ , optInPlace :: Bool
+ , optDiff :: Bool
+ , optVerbose :: Bool
+ }
+
+data Command
+ = Analyze FilePath
+ | Fix FilePath
+ | Report FilePath
+ | ExportPhpIni FilePath
+ | ExportNginx FilePath
+ | ExportGuix FilePath
+ | Help
+ | Version
+
+data OutputFormat = FormatText | FormatJSON | FormatSARIF | FormatHTML
+ deriving (Eq, Show)
+
+data Severity = Critical | High | Medium | Low | Info
+ deriving (Eq, Show, Read)
main :: IO ()
main = do
args <- getArgs
- case args of
- ["--help"] -> printHelp
- ["-h"] -> printHelp
- ["--version"] -> putStrLn "sanctify-php 0.1.0"
- ["analyze", path] -> analyzeCommand path
- ["fix", path] -> fixCommand path
- ["report", path] -> reportCommand path
- ["export", "--php-ini", path] -> exportPhpIniCommand path
- ["export", "--nginx", path] -> exportNginxCommand path
- ["export", "--guix", path] -> exportGuixCommand path
- _ -> do
- putStrLn "Usage: sanctify [options] "
- putStrLn "Run 'sanctify --help' for more information."
- exitFailure
+ opts <- parseArgs args
+ runCommand opts
+
+-- | Parse command-line arguments
+parseArgs :: [String] -> IO Options
+parseArgs args = case args of
+ [] -> printHelp >> exitFailure
+ ("--help":_) -> pure $ Options Help False False FormatText [] [] False False False
+ ("-h":_) -> pure $ Options Help False False FormatText [] [] False False False
+ ("--version":_) -> pure $ Options Version False False FormatText [] [] False False False
+ _ -> parseCommand args defaultOptions
+ where
+ defaultOptions = Options
+ { optCommand = Help
+ , optInteractive = False
+ , optWatch = False
+ , optFormat = FormatText
+ , optSeverity = []
+ , optTypes = []
+ , optInPlace = False
+ , optDiff = False
+ , optVerbose = False
+ }
+
+-- | Parse command and options
+parseCommand :: [String] -> Options -> IO Options
+parseCommand [] opts = pure opts
+parseCommand ("analyze":rest) opts = parseOptions rest (opts { optCommand = Analyze "" })
+parseCommand ("fix":rest) opts = parseOptions rest (opts { optCommand = Fix "" })
+parseCommand ("report":rest) opts = parseOptions rest (opts { optCommand = Report "" })
+parseCommand ("export":"--php-ini":rest) opts = parseOptions rest (opts { optCommand = ExportPhpIni "" })
+parseCommand ("export":"--nginx":rest) opts = parseOptions rest (opts { optCommand = ExportNginx "" })
+parseCommand ("export":"--guix":rest) opts = parseOptions rest (opts { optCommand = ExportGuix "" })
+parseCommand (arg:rest) opts
+ | "--interactive" `isPrefixOf` arg = parseCommand rest (opts { optInteractive = True })
+ | "--watch" `isPrefixOf` arg = parseCommand rest (opts { optWatch = True })
+ | "--in-place" `isPrefixOf` arg = parseCommand rest (opts { optInPlace = True })
+ | "--diff" `isPrefixOf` arg = parseCommand rest (opts { optDiff = True })
+ | "-v" == arg || "--verbose" == arg = parseCommand rest (opts { optVerbose = True })
+ | "--format=json" `isPrefixOf` arg = parseCommand rest (opts { optFormat = FormatJSON })
+ | "--format=sarif" `isPrefixOf` arg = parseCommand rest (opts { optFormat = FormatSARIF })
+ | "--format=html" `isPrefixOf` arg = parseCommand rest (opts { optFormat = FormatHTML })
+ | "--format=text" `isPrefixOf` arg = parseCommand rest (opts { optFormat = FormatText })
+ | "--severity=" `isPrefixOf` arg =
+ let sevs = parseSeverities (drop 11 arg)
+ in parseCommand rest (opts { optSeverity = sevs })
+ | "--type=" `isPrefixOf` arg =
+ let types = T.splitOn "," $ T.pack $ drop 7 arg
+ in parseCommand rest (opts { optTypes = types })
+ | not ("-" `isPrefixOf` arg) = pure $ setPath arg opts
+ | otherwise = do
+ hPutStrLn stderr $ "Unknown option: " ++ arg
+ exitFailure
+
+parseOptions :: [String] -> Options -> IO Options
+parseOptions = parseCommand
+
+setPath :: FilePath -> Options -> Options
+setPath path opts = opts { optCommand = updatePath path (optCommand opts) }
+ where
+ updatePath p (Analyze _) = Analyze p
+ updatePath p (Fix _) = Fix p
+ updatePath p (Report _) = Report p
+ updatePath p (ExportPhpIni _) = ExportPhpIni p
+ updatePath p (ExportNginx _) = ExportNginx p
+ updatePath p (ExportGuix _) = ExportGuix p
+ updatePath _ cmd = cmd
+
+parseSeverities :: String -> [Severity]
+parseSeverities str = catMaybes $ map readSev $ splitOn ',' str
+ where
+ readSev s = case map toLower s of
+ "critical" -> Just Critical
+ "high" -> Just High
+ "medium" -> Just Medium
+ "low" -> Just Low
+ "info" -> Just Info
+ _ -> Nothing
+ toLower c | c >= 'A' && c <= 'Z' = toEnum (fromEnum c + 32)
+ | otherwise = c
+ splitOn _ [] = []
+ splitOn delim s = case break (== delim) s of
+ (a, []) -> [a]
+ (a, _:b) -> a : splitOn delim b
+
+-- | Run the command
+runCommand :: Options -> IO ()
+runCommand opts = case optCommand opts of
+ Help -> printHelp
+ Version -> putStrLn "sanctify-php 0.2.0-alpha"
+ Analyze path -> analyzeCommandNew opts path
+ Fix path -> fixCommandNew opts path
+ Report path -> reportCommandNew opts path
+ ExportPhpIni path -> exportPhpIniCommand path
+ ExportNginx path -> exportNginxCommand path
+ ExportGuix path -> exportGuixCommand path
printHelp :: IO ()
printHelp = putStrLn $ unlines
@@ -61,43 +179,96 @@ printHelp = putStrLn $ unlines
, " --guix Generate Guix channel overrides"
, ""
, "OPTIONS:"
- , " -h, --help Show this help"
- , " --version Show version"
+ , " -h, --help Show this help"
+ , " --version Show version"
+ , " --interactive Interactive fix mode (prompt for each change)"
+ , " --watch Watch mode (re-analyze on file changes)"
+ , " --format= Output format: text, json, sarif, html (default: text)"
+ , " --severity= Filter by severity: critical,high,medium,low,info"
+ , " --type= Filter by issue type (comma-separated)"
+ , " --in-place Apply fixes in-place (modifies files)"
+ , " --diff Show diff preview of changes"
+ , " -v, --verbose Verbose output"
, ""
, "EXAMPLES:"
+ , " # Basic analysis"
, " sanctify analyze ./wp-content/plugins/my-plugin/"
- , " sanctify fix --auto-only ./src/"
- , " sanctify report --format=sarif ./theme/ > report.sarif"
+ , ""
+ , " # Filter high and critical issues only"
+ , " sanctify analyze --severity=high,critical ./src/"
+ , ""
+ , " # Interactive fix with diff preview"
+ , " sanctify fix --interactive --diff ./theme/"
+ , ""
+ , " # Watch mode for development"
+ , " sanctify analyze --watch ./src/"
+ , ""
+ , " # Generate SARIF report for CI/CD"
+ , " sanctify report --format=sarif ./project/ > report.sarif"
+ , ""
+ , " # Export infrastructure configuration"
, " sanctify export --php-ini ./project/ >> php.ini"
, ""
, "For container integration, see:"
, " guix/wordpress-container.scm"
]
--- | Analyze command
-analyzeCommand :: FilePath -> IO ()
-analyzeCommand path = do
+-- | Enhanced analyze command with watch mode and filtering
+analyzeCommandNew :: Options -> FilePath -> IO ()
+analyzeCommandNew opts path
+ | optWatch opts = watchMode opts path analyzeOnce
+ | otherwise = analyzeOnce opts path
+
+analyzeOnce :: Options -> FilePath -> IO ()
+analyzeOnce opts path = do
files <- findPhpFiles path
when (null files) $ do
putStrLn $ "No PHP files found in: " ++ path
exitFailure
- putStrLn $ "Analyzing " ++ show (length files) ++ " PHP files..."
+ when (optVerbose opts) $
+ putStrLn $ "Analyzing " ++ show (length files) ++ " PHP files..."
results <- forM files $ \file -> do
content <- TIO.readFile file
case parsePhpString file content of
Left err -> do
- putStrLn $ " Parse error in " ++ file ++ ": " ++ show err
+ when (optVerbose opts) $
+ putStrLn $ " Parse error in " ++ file ++ ": " ++ show err
pure (file, [], [])
Right ast -> do
- let secIssues = analyzeSecurityIssues ast
+ let secIssues = filterIssues opts $ analyzeSecurityIssues ast
let wpIssues = if isWordPressCode ast
then checkWordPressConstraints ast
else []
pure (file, secIssues, wpIssues)
- -- Print results
+ -- Output results based on format
+ case optFormat opts of
+ FormatText -> outputTextResults opts results
+ FormatJSON -> outputJSONResults results
+ FormatSARIF -> outputSARIFResults results
+ FormatHTML -> outputHTMLResults results
+
+ let totalIssues = sum $ map (\(_, s, w) -> length s + length w) results
+ if totalIssues > 0
+ then exitFailure
+ else exitSuccess
+
+-- | Filter issues by severity and type
+filterIssues :: Options -> [SecurityIssue] -> [SecurityIssue]
+filterIssues opts issues =
+ let bySeverity = if null (optSeverity opts)
+ then issues
+ else filter (\i -> issueSeverity i `elem` optSeverity opts) issues
+ byType = if null (optTypes opts)
+ then bySeverity
+ else filter (\i -> T.pack (show (issueType i)) `elem` optTypes opts) bySeverity
+ in byType
+
+-- | Output results as text
+outputTextResults :: Options -> [(FilePath, [SecurityIssue], [WordPressIssue])] -> IO ()
+outputTextResults opts results = do
let totalSec = sum $ map (\(_, s, _) -> length s) results
let totalWp = sum $ map (\(_, _, w) -> length w) results
@@ -111,65 +282,260 @@ analyzeCommand path = do
putStrLn $ file ++ ":"
forM_ secIssues $ \issue ->
putStrLn $ " [" ++ show (issueSeverity issue) ++ "] " ++ T.unpack (issueDescription issue)
+ ++ " (line " ++ show (posLine $ issueLocation issue) ++ ")"
forM_ wpIssues $ \issue ->
putStrLn $ " [WP:" ++ show (wpIssueType issue) ++ "] " ++ T.unpack (wpDescription issue)
putStrLn ""
- if totalSec + totalWp > 0
- then exitFailure
- else exitSuccess
+-- | Output results as JSON
+outputJSONResults :: [(FilePath, [SecurityIssue], [WordPressIssue])] -> IO ()
+outputJSONResults results = do
+ putStrLn "{"
+ putStrLn " \"issues\": ["
+ let allIssues = concatMap (\(file, sec, wp) ->
+ map (\i -> " {\"file\": \"" ++ file ++ "\", \"type\": \"security\", \"severity\": \"" ++ show (issueSeverity i) ++ "\", \"message\": \"" ++ T.unpack (issueDescription i) ++ "\", \"line\": " ++ show (posLine $ issueLocation i) ++ "}") sec
+ ++ map (\i -> " {\"file\": \"" ++ file ++ "\", \"type\": \"wordpress\", \"message\": \"" ++ T.unpack (wpDescription i) ++ "\"}") wp) results
+ putStrLn $ concat $ insertCommas allIssues
+ putStrLn " ]"
+ putStrLn "}"
+ where
+ insertCommas [] = []
+ insertCommas [x] = [x]
+ insertCommas (x:xs) = (x ++ ",") : insertCommas xs
--- | Fix command
-fixCommand :: FilePath -> IO ()
-fixCommand path = do
+-- | Output results as SARIF
+outputSARIFResults :: [(FilePath, [SecurityIssue], [WordPressIssue])] -> IO ()
+outputSARIFResults results = do
+ putStrLn "{"
+ putStrLn " \"version\": \"2.1.0\","
+ putStrLn " \"$schema\": \"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\","
+ putStrLn " \"runs\": [{"
+ putStrLn " \"tool\": {"
+ putStrLn " \"driver\": {"
+ putStrLn " \"name\": \"sanctify-php\","
+ putStrLn " \"version\": \"0.2.0-alpha\""
+ putStrLn " }"
+ putStrLn " },"
+ putStrLn " \"results\": ["
+ let sarifResults = concatMap (\(file, sec, _) ->
+ map (\i -> " {\"ruleId\": \"" ++ show (issueType i) ++ "\", \"level\": \"" ++ severityToLevel (issueSeverity i) ++ "\", \"message\": {\"text\": \"" ++ T.unpack (issueDescription i) ++ "\"}, \"locations\": [{\"physicalLocation\": {\"artifactLocation\": {\"uri\": \"" ++ file ++ "\"}, \"region\": {\"startLine\": " ++ show (posLine $ issueLocation i) ++ "}}}]}") sec) results
+ putStrLn $ concat $ insertCommas sarifResults
+ putStrLn " ]"
+ putStrLn " }]"
+ putStrLn "}"
+ where
+ severityToLevel Critical = "error"
+ severityToLevel High = "error"
+ severityToLevel Medium = "warning"
+ severityToLevel Low = "note"
+ severityToLevel Info = "note"
+ insertCommas [] = []
+ insertCommas [x] = [x]
+ insertCommas (x:xs) = (x ++ ",") : insertCommas xs
+
+-- | Output results as HTML
+outputHTMLResults :: [(FilePath, [SecurityIssue], [WordPressIssue])] -> IO ()
+outputHTMLResults results = do
+ putStrLn "Sanctify-PHP Report"
+ putStrLn ""
+ putStrLn "