chore: Sync MokoStandards 04.02.29 #104

Closed
jmiller-moko wants to merge 38 commits from chore/sync-mokostandards-v04.02.29 into main
17 changed files with 2305 additions and 1736 deletions

20
.github/.mokostandards vendored Normal file
View File

@@ -0,0 +1,20 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
# DEFGROUP: MokoStandards.Templates.Config
# INGROUP: MokoStandards.Templates
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/configs/moko-standards.yml
# VERSION: 04.02.30
# BRIEF: Governance attachment template — synced to .mokostandards in every governed repository
# NOTE: Tokens replaced at sync time: mokoconsulting-tech, MokoCassiopeia, waas-component, 04.02.29
#
# This file is managed automatically by MokoStandards bulk sync.
# Do not edit manually — changes will be overwritten on the next sync.
# To update governance settings, open a PR in MokoStandards instead:
# https://github.com/mokoconsulting-tech/MokoStandards
standards_source: "https://github.com/mokoconsulting-tech/MokoStandards"
standards_version: "04.02.29"
platform: "waas-component"
governed_repo: "mokoconsulting-tech/MokoCassiopeia"

89
.github/workflows/auto-dev-issue.yml vendored Normal file
View File

@@ -0,0 +1,89 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow
# INGROUP: MokoStandards.Automation
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/auto-dev-issue.yml
# VERSION: 04.02.30
# BRIEF: Auto-create tracking issue when a dev/** branch is pushed
# NOTE: Synced via bulk-repo-sync to .github/workflows/auto-dev-issue.yml in all governed repos.
name: Auto Dev Branch Issue
on:
create:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
issues: write
jobs:
create-issue:
name: Create version tracking issue
runs-on: ubuntu-latest
if: >-
github.event.ref_type == 'branch' &&
startsWith(github.event.ref, 'dev/')
steps:
- name: Create tracking issue
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
BRANCH="${{ github.event.ref }}"
VERSION="${BRANCH#dev/}"
REPO="${{ github.repository }}"
ACTOR="${{ github.actor }}"
NOW=$(date -u '+%Y-%m-%d %H:%M UTC')
TITLE="feat(${VERSION}): Development tracking for ${BRANCH}"
BODY="## Development Branch Created
| Field | Value |
|-------|-------|
| **Branch** | \`${BRANCH}\` |
| **Version** | \`${VERSION}\` |
| **Created by** | @${ACTOR} |
| **Created at** | ${NOW} |
| **Repository** | \`${REPO}\` |
## Checklist
- [ ] Feature development complete
- [ ] Tests passing
- [ ] README.md version bumped to \`${VERSION}\`
- [ ] CHANGELOG.md updated
- [ ] PR created targeting \`main\`
- [ ] Code reviewed and approved
- [ ] Merged to \`main\`
---
*Auto-created by [auto-dev-issue.yml](.github/workflows/auto-dev-issue.yml) on branch creation.*"
# Dedent heredoc
BODY=$(echo "$BODY" | sed 's/^ //')
# Check for existing issue with same title prefix
EXISTING=$(gh api "repos/${REPO}/issues?state=open&per_page=5" \
--jq ".[] | select(.title | startswith(\"feat(${VERSION})\")) | .number" 2>/dev/null | head -1)
if [ -n "$EXISTING" ]; then
echo " Issue #${EXISTING} already exists for ${VERSION}" >> $GITHUB_STEP_SUMMARY
else
ISSUE_URL=$(gh issue create \
--repo "$REPO" \
--title "$TITLE" \
--body "$BODY" \
--label "type: feature,version" \
--assignee "jmiller-moko" 2>&1)
echo "✅ Created tracking issue: ${ISSUE_URL}" >> $GITHUB_STEP_SUMMARY
fi

View File

@@ -1,7 +1,5 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
@@ -9,12 +7,26 @@
# INGROUP: MokoStandards.Release
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/auto-release.yml
# VERSION: 04.01.00
# BRIEF: Auto-create a GitHub Release on every push to main with version from README.md
# NOTE: Synced via bulk-repo-sync to .github/workflows/auto-release.yml in all governed repos.
# For Dolibarr (crm-module) repos, also updates $this->version in the module descriptor.
# VERSION: 04.02.30
# BRIEF: Unified build & release pipeline — version branch, platform version, badges, tag, release
#
# ╔════════════════════════════════════════════════════════════════════════╗
# ║ BUILD & RELEASE PIPELINE ║
# ╠════════════════════════════════════════════════════════════════════════╣
# ║ ║
# ║ Triggers on push to main (skips bot commits + [skip ci]): ║
# ║ ║
# ║ 1. Read version from README.md ║
# ║ 2. Create version/XX.YY.ZZ branch (snapshot) ║
# ║ 3. Set platform version (Dolibarr $this->version, Joomla <version>) ║
# ║ 4. Update [VERSION: XX.YY.ZZ] badges in markdown files ║
# ║ 5. Write update.txt for Dolibarr module update checks ║
# ║ 6. Create git tag vXX.YY.ZZ ║
# ║ 7. Create GitHub Release with changelog notes ║
# ║ ║
# ╚════════════════════════════════════════════════════════════════════════╝
name: Auto Release
name: Build & Release
on:
push:
@@ -22,14 +34,16 @@ on:
- main
- master
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
jobs:
release:
name: Create Release
name: Build & Release Pipeline
runs-on: ubuntu-latest
# Skip bot commits (version sync, [skip ci]) to avoid infinite loops
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
github.actor != 'github-actions[bot]'
@@ -41,123 +55,250 @@ jobs:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
- name: Extract version from README.md
- name: Setup MokoStandards tools
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch version/04.02.29 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
# ── STEP 1: Read version ───────────────────────────────────────────
- name: "Step 1: Read version from README.md"
id: version
run: |
VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1)
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
if [ -z "$VERSION" ]; then
echo " No VERSION found in README.md — skipping release"
echo " No VERSION in README.md — skipping release"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
echo "branch=version/${VERSION}" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "✅ Version: $VERSION (tag: v${VERSION})"
echo "✅ Version: $VERSION"
- name: Check if tag already exists
- name: Check if already released
if: steps.version.outputs.skip != 'true'
id: tag_check
id: check
run: |
TAG="${{ steps.version.outputs.tag }}"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo " Tag $TAG already exists — skipping release"
echo "exists=true" >> "$GITHUB_OUTPUT"
BRANCH="${{ steps.version.outputs.branch }}"
TAG_EXISTS=false
BRANCH_EXISTS=false
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
git ls-remote --heads origin "$BRANCH" 2>/dev/null | grep -q "$BRANCH" && BRANCH_EXISTS=true
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
echo "branch_exists=$BRANCH_EXISTS" >> "$GITHUB_OUTPUT"
if [ "$TAG_EXISTS" = "true" ] && [ "$BRANCH_EXISTS" = "true" ]; then
echo "already_released=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "already_released=false" >> "$GITHUB_OUTPUT"
fi
- name: Update Dolibarr module version
# ── SANITY CHECKS ────────────────────────────────────────────────────
- name: "Sanity: Platform-specific validation"
if: >-
steps.version.outputs.skip != 'true' &&
steps.tag_check.outputs.exists != 'true'
steps.check.outputs.already_released != 'true'
run: |
PLATFORM=""
if [ -f ".moko-standards" ]; then
PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"')
fi
VERSION="${{ steps.version.outputs.version }}"
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null)
ERRORS=0
echo "## 🔍 Pre-Release Sanity Checks" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Platform: \`${PLATFORM}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Common checks
if [ ! -f "LICENSE" ]; then
echo "❌ Missing LICENSE file" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "✅ LICENSE" >> $GITHUB_STEP_SUMMARY
fi
if [ ! -d "src" ]; then
echo "⚠️ No src/ directory" >> $GITHUB_STEP_SUMMARY
else
echo "✅ src/ directory" >> $GITHUB_STEP_SUMMARY
fi
# Dolibarr-specific checks
if [ "$PLATFORM" = "crm-module" ]; then
echo "📦 Dolibarr release — setting module version to '${VERSION}'"
# Update $this->version in the module descriptor (core/modules/mod*.class.php)
find . -path "*/core/modules/mod*.class.php" -exec \
sed -i "s/\(\$this->version\s*=\s*\)['\"][^'\"]*['\"]/\1'${VERSION}'/" {} + 2>/dev/null || true
MOD_FILE=$(find src -path "*/core/modules/mod*.class.php" -print -quit 2>/dev/null)
if [ -z "$MOD_FILE" ]; then
echo "❌ No module descriptor (src/core/modules/mod*.class.php)" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "✅ Module descriptor: \`${MOD_FILE}\`" >> $GITHUB_STEP_SUMMARY
# Check module number
NUMERO=$(grep -oP '\$this->numero\s*=\s*\K\d+' "$MOD_FILE" 2>/dev/null || echo "0")
if [ "$NUMERO" = "0" ] || [ -z "$NUMERO" ]; then
echo "❌ Module number (\$this->numero) is 0 or not set" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "✅ Module number: ${NUMERO}" >> $GITHUB_STEP_SUMMARY
fi
# Check url_last_version exists
if grep -q 'url_last_version' "$MOD_FILE" 2>/dev/null; then
echo "✅ url_last_version is set" >> $GITHUB_STEP_SUMMARY
else
echo "⚠️ url_last_version not set — update checks won't work" >> $GITHUB_STEP_SUMMARY
fi
fi
fi
# Joomla-specific checks
if [ "$PLATFORM" = "waas-component" ]; then
echo "📦 Joomla release — setting manifest version to '${VERSION}'"
# Update <version> tag in Joomla XML manifest files
find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | while read -r manifest; do
sed -i "s|<version>[^<]*</version>|<version>${VERSION}</version>|" "$manifest" 2>/dev/null || true
done
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "❌ No Joomla XML manifest found" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "✅ Manifest: \`${MANIFEST}\`" >> $GITHUB_STEP_SUMMARY
# Check extension type
TYPE=$(grep -oP '<extension[^>]+type="\K[^"]+' "$MANIFEST" 2>/dev/null)
echo "✅ Extension type: ${TYPE:-unknown}" >> $GITHUB_STEP_SUMMARY
fi
fi
# Commit the version update if anything changed
if ! git diff --quiet; then
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$ERRORS" -gt 0 ]; then
echo "**❌ ${ERRORS} error(s) — release may be incomplete**" >> $GITHUB_STEP_SUMMARY
else
echo "**✅ All sanity checks passed**" >> $GITHUB_STEP_SUMMARY
fi
# ── STEP 2: Create version branch ──────────────────────────────────
- name: "Step 2: Create version branch"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.branch_exists != 'true'
run: |
BRANCH="${{ steps.version.outputs.branch }}"
git checkout -b "$BRANCH"
git push origin "$BRANCH"
echo "🌿 Created branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
# ── STEP 3: Set platform version ───────────────────────────────────
- name: "Step 3: Set platform version"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
php /tmp/mokostandards/api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
# ── STEP 4: Update version badges ──────────────────────────────────
- name: "Step 4: Update version badges"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
find . -name "*.md" ! -path "./.git/*" ! -path "./vendor/*" | while read -r f; do
if grep -q '\[VERSION:' "$f" 2>/dev/null; then
sed -i "s/\[VERSION:[[:space:]]*[0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\}\]/[VERSION: ${VERSION}]/" "$f"
fi
done
# ── STEP 5: Write update.txt (Dolibarr) ────────────────────────────
- name: "Step 5: Write update.txt"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null)
if [ "$PLATFORM" = "crm-module" ]; then
VERSION="${{ steps.version.outputs.version }}"
printf '%s' "$VERSION" > update.txt
echo "📦 update.txt: ${VERSION}" >> $GITHUB_STEP_SUMMARY
fi
# ── Commit all changes ─────────────────────────────────────────────
- name: Commit release changes
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
if git diff --quiet && git diff --cached --quiet; then
echo " No changes to commit"
exit 0
fi
VERSION="${{ steps.version.outputs.version }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore(release): set version to ${VERSION} [skip ci]" \
git commit -m "chore(release): build ${VERSION} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
fi
- name: Extract changelog entry
# ── STEP 6: Create tag ─────────────────────────────────────────────
- name: "Step 6: Create git tag"
if: >-
steps.version.outputs.skip != 'true' &&
steps.tag_check.outputs.exists != 'true'
id: changelog
steps.check.outputs.tag_exists != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
git tag "$TAG"
git push origin "$TAG"
echo "🏷️ Tag: ${TAG}" >> $GITHUB_STEP_SUMMARY
# Try to extract the section for this version from CHANGELOG.md
NOTES=""
if [ -f "CHANGELOG.md" ]; then
# Extract text between this version's heading and the next heading
NOTES=$(awk "/^##.*${VERSION}/,/^## /" CHANGELOG.md | head -50 | sed '1d;$d')
fi
if [ -z "$NOTES" ]; then
NOTES="Release ${VERSION}"
fi
# Write to file to avoid shell escaping issues
echo "$NOTES" > /tmp/release_notes.md
echo "✅ Release notes prepared"
- name: Create tag and release
# ── STEP 7: Create GitHub Release ──────────────────────────────────
- name: "Step 7: Create GitHub Release"
if: >-
steps.version.outputs.skip != 'true' &&
steps.tag_check.outputs.exists != 'true'
steps.check.outputs.tag_exists != 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
TAG="${{ steps.version.outputs.tag }}"
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
BRANCH="${{ steps.version.outputs.branch }}"
# Create the tag
git tag "$TAG"
git push origin "$TAG"
NOTES=$(php /tmp/mokostandards/api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
echo "$NOTES" > /tmp/release_notes.md
# Create the release
gh release create "$TAG" \
--title "${VERSION}" \
--notes-file /tmp/release_notes.md \
--target main
--target "$BRANCH"
echo "🚀 Release ${VERSION} created: $TAG"
echo "🚀 Release ${VERSION}" >> $GITHUB_STEP_SUMMARY
- name: Summary
if: steps.version.outputs.skip != 'true'
# ── Summary ────────────────────────────────────────────────────────
- name: Pipeline Summary
if: always()
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
if [ "${{ steps.tag_check.outputs.exists }}" = "true" ]; then
echo "## Release — ${VERSION}" >> $GITHUB_STEP_SUMMARY
echo "Tag \`${TAG}\` already exists — no new release created." >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
echo "## ⏭️ Release Skipped" >> $GITHUB_STEP_SUMMARY
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
else
echo "## 🚀 Release — ${VERSION}" >> $GITHUB_STEP_SUMMARY
echo "Created tag \`${TAG}\` and GitHub Release." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## ✅ Build & Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi

View File

@@ -5,15 +5,17 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow
# DEFGROUP: GitHub.Workflow.Template
# INGROUP: MokoStandards.Security
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /.github/workflows/codeql-analysis.yml
# VERSION: 04.01.00
# BRIEF: CodeQL security scanning workflow for PHP codebase
# NOTE: Repository is PHP-only (v04.00.04). Python was removed Feb 12, 2026.
# PATH: /templates/workflows/generic/codeql-analysis.yml
# VERSION: 04.02.30
# BRIEF: CodeQL security scanning workflow (generic — all repo types)
# NOTE: Deployed to .github/workflows/codeql-analysis.yml in governed repos.
# CodeQL does not support PHP directly; JavaScript scans JSON/YAML/shell.
# For PHP-specific security scanning see standards-compliance.yml.
name: "CodeQL Security Scanning"
name: CodeQL Security Scanning
on:
push:
@@ -28,7 +30,7 @@ on:
- dev/**
- rc/**
schedule:
# Run weekly on Monday at 6:00 AM UTC
# Weekly on Monday at 06:00 UTC
- cron: '0 6 * * 1'
workflow_dispatch:
@@ -40,65 +42,60 @@ permissions:
jobs:
analyze:
name: Configuration Security Scan
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 360
# No language matrix - PHP-only repository
# CodeQL scans workflow files, configs, and scripts for security issues
# PHP security handled by SecurityValidator enterprise library
strategy:
fail-fast: false
matrix:
# CodeQL does not support PHP. Use 'javascript' to scan JSON, YAML,
# and shell scripts. Add 'actions' to scan GitHub Actions workflows.
language: ['javascript', 'actions']
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4
uses: github/codeql-action/init@v3
with:
# No languages specified - scan configurations only
# Reference explicit config to scan YAML, JSON, shell scripts
config-file: ./.github/codeql/codeql-config.yml
# Use security-extended query suite for comprehensive coverage
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
# Skip autobuild - no code compilation needed for config scanning
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4
uses: github/codeql-action/analyze@v3
with:
category: "/language:config"
category: "/language:${{ matrix.language }}"
upload: true
output: sarif-results
wait-for-processing: true
- name: Upload SARIF results (optional)
- name: Upload SARIF results
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v4.5.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.5.0
with:
name: codeql-results-config
name: codeql-results-${{ matrix.language }}
path: sarif-results
retention-days: 30
- name: Check for Critical/High Findings
- name: Step summary
if: always()
run: |
echo "### 🔍 CodeQL Security Analysis Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Scan Type**: Configuration Security" >> $GITHUB_STEP_SUMMARY
echo "**Query Suite**: security-extended, security-and-quality" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Note**: MokoStandards is PHP-only (v04.00.04)." >> $GITHUB_STEP_SUMMARY
echo "This scan analyzes workflow files, JSON configs, YAML, and shell scripts." >> $GITHUB_STEP_SUMMARY
echo "For PHP-specific security: Use PHP SecurityValidator enterprise library." >> $GITHUB_STEP_SUMMARY
echo "### 🔍 CodeQL — ${{ matrix.language }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
URL="https://github.com/${{ github.repository }}/security/code-scanning"
echo "Check the [Security tab]($URL) for detailed findings." >> $GITHUB_STEP_SUMMARY
echo "See the [Security tab]($URL) for findings." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Response Requirements**:" >> $GITHUB_STEP_SUMMARY
echo "- Critical: Fix within 7 days" >> $GITHUB_STEP_SUMMARY
echo "- High: Fix within 14 days" >> $GITHUB_STEP_SUMMARY
echo "- Medium: Fix within 30 days" >> $GITHUB_STEP_SUMMARY
echo "- Low: Fix within 60 days or next release" >> $GITHUB_STEP_SUMMARY
echo "| Severity | SLA |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-----|" >> $GITHUB_STEP_SUMMARY
echo "| Critical | 7 days |" >> $GITHUB_STEP_SUMMARY
echo "| High | 14 days |" >> $GITHUB_STEP_SUMMARY
echo "| Medium | 30 days |" >> $GITHUB_STEP_SUMMARY
echo "| Low | 60 days / next release |" >> $GITHUB_STEP_SUMMARY
summary:
name: Security Scan Summary
@@ -107,17 +104,12 @@ jobs:
if: always()
steps:
- name: Generate Summary
- name: Summary
run: |
echo "### 🛡️ Security Scanning Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "All CodeQL security scans have completed." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
echo "### 🛡️ CodeQL Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
SECURITY_URL="https://github.com/${{ github.repository }}/security"
echo "" >> $GITHUB_STEP_SUMMARY
echo "📊 [View all security alerts]($SECURITY_URL)" >> $GITHUB_STEP_SUMMARY
POLICY_URL="https://github.com/${{ github.repository }}"
POLICY_URL="${POLICY_URL}/blob/main/docs/policy/security-scanning.md"
echo "📋 [Security scanning policy]($POLICY_URL)" >> $GITHUB_STEP_SUMMARY

View File

@@ -22,7 +22,7 @@
# INGROUP: MokoStandards.Deploy
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/deploy-demo.yml
# VERSION: 04.01.00
# VERSION: 04.02.30
# BRIEF: SFTP deployment workflow for demo server — synced to all governed repos
# NOTE: Synced via bulk-repo-sync to .github/workflows/deploy-demo.yml in all governed repos.
# Port is resolved in order: DEMO_FTP_PORT variable → :port suffix in DEMO_FTP_HOST → 22.
@@ -70,6 +70,9 @@ permissions:
contents: read
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
check-permission:
name: Verify Deployment Permission
@@ -241,7 +244,6 @@ jobs:
fi
done
$SKIP && continue
if [ -f ".gitignore" ]; then
if [ -f ".gitignore" ]; then
git check-ignore -q "$rel" 2>/dev/null && {
IGNORED_FILES+=("$rel | .gitignore")
@@ -345,8 +347,8 @@ jobs:
# ── Platform-specific path safety guards ──────────────────────────────
PLATFORM=""
if [ -f ".moko-standards" ]; then
PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"')
MOKO_FILE=".github/.mokostandards"; [ ! -f "$MOKO_FILE" ] && MOKO_FILE=".mokostandards"; if [ -f "$MOKO_FILE" ]; then
PLATFORM=$(grep -E '^platform:' "$MOKO_FILE" | sed 's/.*:[[:space:]]*//' | tr -d '"')
fi
if [ "$PLATFORM" = "crm-module" ]; then
@@ -407,7 +409,7 @@ jobs:
- name: Setup PHP
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.31.0
uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0
with:
php-version: '8.1'
tools: composer
@@ -418,14 +420,17 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --quiet \
git clone --depth 1 --branch version/04.02.29 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Clear remote destination folder
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
- name: Clear remote destination folder (manual only)
if: >-
steps.source.outputs.skip == 'false' &&
steps.remote.outputs.skip != 'true' &&
inputs.clear_remote == true
env:
SFTP_HOST: ${{ steps.conn.outputs.host }}
SFTP_PORT: ${{ steps.conn.outputs.port }}
@@ -578,7 +583,7 @@ jobs:
rm -f /tmp/deploy_key /tmp/sftp-config.json
- name: Create or update failure issue
if: failure()
if: failure() && steps.remote.outputs.skip != 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
@@ -620,22 +625,22 @@ jobs:
--force 2>/dev/null || true
# Look for an existing open deploy-failure issue
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=open&per_page=1" \
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" \
--jq '.[0].number' 2>/dev/null)
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
gh api "repos/${REPO}/issues/${EXISTING}" \
-X PATCH \
-f title="$TITLE" \
-f body="$BODY" \
-f body="$BODY" \n -f state="open" \
--silent
echo "📋 Failure issue #${EXISTING} updated: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
echo "📋 Failure issue #${EXISTING} updated/reopened: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
else
gh issue create \
--repo "$REPO" \
--title "$TITLE" \
--body "$BODY" \
--label "$LABEL" \
--label "$LABEL" \n --assignee "jmiller-moko" \
| tee -a "$GITHUB_STEP_SUMMARY"
fi

View File

@@ -22,7 +22,7 @@
# INGROUP: MokoStandards.Deploy
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/deploy-dev.yml
# VERSION: 04.01.00
# VERSION: 04.02.30
# BRIEF: SFTP deployment workflow for development server — synced to all governed repos
# NOTE: Synced via bulk-repo-sync to .github/workflows/deploy-dev.yml in all governed repos.
# Port is resolved in order: DEV_FTP_PORT variable → :port suffix in DEV_FTP_HOST → 22.
@@ -73,6 +73,9 @@ permissions:
contents: read
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
check-permission:
name: Verify Deployment Permission
@@ -347,8 +350,8 @@ jobs:
# ── Platform-specific path safety guards ──────────────────────────────
PLATFORM=""
if [ -f ".moko-standards" ]; then
PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"')
MOKO_FILE=".github/.mokostandards"; [ ! -f "$MOKO_FILE" ] && MOKO_FILE=".mokostandards"; if [ -f "$MOKO_FILE" ]; then
PLATFORM=$(grep -oP '^platform:.*' "$MOKO_FILE" 2>/dev/null || true)
fi
if [ "$PLATFORM" = "crm-module" ]; then
@@ -409,7 +412,7 @@ jobs:
- name: Setup PHP
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.31.0
uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0
with:
php-version: '8.1'
tools: composer
@@ -420,14 +423,17 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --quiet \
git clone --depth 1 --branch version/04.02.29 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Clear remote destination folder
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
- name: Clear remote destination folder (manual only)
if: >-
steps.source.outputs.skip == 'false' &&
steps.remote.outputs.skip != 'true' &&
inputs.clear_remote == true
env:
SFTP_HOST: ${{ steps.conn.outputs.host }}
SFTP_PORT: ${{ steps.conn.outputs.port }}
@@ -574,24 +580,8 @@ jobs:
DEPLOY_ARGS+=(--key-passphrase "$SFTP_PASSWORD")
fi
# ── For Dolibarr (crm-module): set version to "development" before deploy
PLATFORM=""
if [ -f ".moko-standards" ]; then
PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"')
fi
if [ "$PLATFORM" = "crm-module" ]; then
echo "📦 Dolibarr dev deploy — setting module version to 'development'"
find "$SOURCE_DIR" -path "*/core/modules/mod*.class.php" -exec \
sed -i "s/\(\$this->version\s*=\s*\)['\"][^'\"]*['\"]/\1'development'/" {} + 2>/dev/null || true
fi
if [ "$PLATFORM" = "waas-component" ]; then
echo "📦 Joomla dev deploy — setting manifest version to 'development'"
find "$SOURCE_DIR" -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | while read -r manifest; do
sed -i "s|<version>[^<]*</version>|<version>development</version>|" "$manifest" 2>/dev/null || true
done
fi
# Set platform version to "development" before deploy (Dolibarr + Joomla)
php /tmp/mokostandards/api/cli/version_set_platform.php --path . --version development
php /tmp/mokostandards/api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
# (deploy-sftp.php handles dotfile skipping and .ftp_ignore natively)
@@ -641,22 +631,22 @@ jobs:
--force 2>/dev/null || true
# Look for an existing open deploy-failure issue
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=open&per_page=1" \
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" \
--jq '.[0].number' 2>/dev/null)
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
gh api "repos/${REPO}/issues/${EXISTING}" \
-X PATCH \
-f title="$TITLE" \
-f body="$BODY" \
-f body="$BODY" \n -f state="open" \
--silent
echo "📋 Failure issue #${EXISTING} updated: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
echo "📋 Failure issue #${EXISTING} updated/reopened: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
else
gh issue create \
--repo "$REPO" \
--title "$TITLE" \
--body "$BODY" \
--label "$LABEL" \
--label "$LABEL" \n --assignee "jmiller-moko" \
| tee -a "$GITHUB_STEP_SUMMARY"
fi

View File

@@ -22,7 +22,7 @@
# INGROUP: MokoStandards.Deploy
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/deploy-rs.yml
# VERSION: 04.01.00
# VERSION: 04.02.30
# BRIEF: SFTP deployment workflow for release staging server — synced to all governed repos
# NOTE: Synced via bulk-repo-sync to .github/workflows/deploy-rs.yml in all governed repos.
# Port is resolved in order: RS_FTP_PORT variable → :port suffix in RS_FTP_HOST → 22.
@@ -70,6 +70,9 @@ permissions:
contents: read
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
check-permission:
name: Verify Deployment Permission
@@ -344,8 +347,8 @@ jobs:
# ── Platform-specific path safety guards ──────────────────────────────
PLATFORM=""
if [ -f ".moko-standards" ]; then
PLATFORM=$(grep -E '^platform:' .moko-standards | sed 's/.*:[[:space:]]*//' | tr -d '"')
MOKO_FILE=".github/.mokostandards"; [ ! -f "$MOKO_FILE" ] && MOKO_FILE=".mokostandards"; if [ -f "$MOKO_FILE" ]; then
PLATFORM=$(grep -E '^platform:' "$MOKO_FILE" | sed 's/.*:[[:space:]]*//' | tr -d '"')
fi
# RS deployment: no path restrictions for any platform
@@ -387,7 +390,7 @@ jobs:
- name: Setup PHP
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.31.0
uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0
with:
php-version: '8.1'
tools: composer
@@ -398,14 +401,17 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --quiet \
git clone --depth 1 --branch version/04.02.29 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Clear remote destination folder
if: steps.source.outputs.skip == 'false' && steps.remote.outputs.skip != 'true'
- name: Clear remote destination folder (manual only)
if: >-
steps.source.outputs.skip == 'false' &&
steps.remote.outputs.skip != 'true' &&
inputs.clear_remote == true
env:
SFTP_HOST: ${{ steps.conn.outputs.host }}
SFTP_PORT: ${{ steps.conn.outputs.port }}
@@ -558,7 +564,7 @@ jobs:
rm -f /tmp/deploy_key /tmp/sftp-config.json
- name: Create or update failure issue
if: failure()
if: failure() && steps.remote.outputs.skip != 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
@@ -599,8 +605,8 @@ jobs:
--description "Automated deploy failure tracking" \
--force 2>/dev/null || true
# Look for an existing open deploy-failure issue
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=open&per_page=1" \
# Look for an existing deploy-failure issue (any state — reopen if closed)
EXISTING=$(gh api "repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" \
--jq '.[0].number' 2>/dev/null)
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
@@ -608,14 +614,16 @@ jobs:
-X PATCH \
-f title="$TITLE" \
-f body="$BODY" \
-f state="open" \
--silent
echo "📋 Failure issue #${EXISTING} updated: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
echo "📋 Failure issue #${EXISTING} updated/reopened: ${REPO}" >> "$GITHUB_STEP_SUMMARY"
else
gh issue create \
--repo "$REPO" \
--title "$TITLE" \
--body "$BODY" \
--label "$LABEL" \
--assignee "jmiller-moko" \
| tee -a "$GITHUB_STEP_SUMMARY"
fi

View File

@@ -22,7 +22,7 @@
# INGROUP: MokoStandards.Firewall
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/enterprise-firewall-setup.yml
# VERSION: 04.01.00
# VERSION: 04.02.30
# BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server
# NOTE: Reads DEV_FTP_HOST / DEV_FTP_PORT variables to include SFTP egress rules alongside HTTPS rules.

View File

@@ -10,8 +10,8 @@
# INGROUP: MokoStandards.Validation
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /.github/workflows/repo_health.yml
# VERSION: 04.01.00
# BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts.
# VERSION: 04.04.01
# BRIEF: Dolibarr module health checks — validates release config, module descriptor, repo artifacts, and scripts governance.
# NOTE: Field is user-managed.
# ============================================================================
@@ -29,7 +29,7 @@ on:
workflow_dispatch:
inputs:
profile:
description: Which configuration profile to validate. release checks SFTP variables used by release pipeline. scripts checks baseline script prerequisites. repo runs repository health only. al[...]
description: 'Validation profile: all, release, scripts, or repo'
required: true
default: all
type: choice
@@ -39,19 +39,7 @@ on:
- scripts
- repo
pull_request:
paths:
- .github/workflows/**
- scripts/**
- docs/**
- dev/**
push:
branches:
- main
paths:
- .github/workflows/**
- scripts/**
- docs/**
- dev/**
permissions:
contents: read
@@ -68,10 +56,10 @@ env:
# Repo health policy
# Files are listed as-is; directories must end with a trailing slash.
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.github/workflows/,src/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.github/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,docs/,update.txt
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
REPO_DISALLOWED_FILES: TODO.md,todo.md,update.json
# Extended checks toggles
EXTENDED_CHECKS: "true"
@@ -82,6 +70,7 @@ env:
WORKFLOWS_DIR: .github/workflows
SHELLCHECK_PATTERN: '*.sh'
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
access_check:
@@ -412,6 +401,15 @@ jobs:
exit 0
fi
# Source directory: src/ or htdocs/ (either is valid)
if [ -d "src" ]; then
SOURCE_DIR="src"
elif [ -d "htdocs" ]; then
SOURCE_DIR="htdocs"
else
missing_required+=("src/ or htdocs/ (source directory required)")
fi
IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}"
IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}"
IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"
@@ -561,6 +559,61 @@ jobs:
} >> "${GITHUB_STEP_SUMMARY}"
fi
# ── Dolibarr-specific checks ──────────────────────────────────────
dolibarr_findings=()
# Module descriptor: src/core/modules/mod*.class.php
MOD_FILE="$(find src htdocs -path '*/core/modules/mod*.class.php' -print -quit 2>/dev/null || true)"
if [ -z "${MOD_FILE}" ]; then
dolibarr_findings+=("Module descriptor not found (src/core/modules/mod*.class.php)")
else
# Check $this->numero is set and non-zero
if ! grep -qP '\$this->numero\s*=\s*[1-9]' "${MOD_FILE}"; then
dolibarr_findings+=("Module descriptor: \$this->numero not set or is zero")
fi
# Check $this->version is not hardcoded (should be set by workflow)
if grep -qP "\\\$this->version\s*=\s*'[0-9]" "${MOD_FILE}"; then
dolibarr_findings+=("Module descriptor: \$this->version appears hardcoded (should be set by deploy/release workflow)")
fi
# Check url_last_version points to update.txt
if grep -qP 'url_last_version.*update\.json' "${MOD_FILE}"; then
dolibarr_findings+=("Module descriptor: url_last_version points to update.json (must be update.txt)")
fi
# Check url_last_version contains /main/ for main branch
CURRENT_BRANCH="${GITHUB_REF_NAME:-main}"
if [ "${CURRENT_BRANCH}" = "main" ] && ! grep -qP 'url_last_version.*\/main\/' "${MOD_FILE}"; then
dolibarr_findings+=("Module descriptor: url_last_version does not reference /main/ branch")
fi
fi
# Source README should exist (Dolibarr module store requirement)
if [ -n "${SOURCE_DIR:-}" ] && [ ! -f "${SOURCE_DIR}/README.md" ]; then
dolibarr_findings+=("${SOURCE_DIR}/README.md missing (required for Dolibarr module store)")
fi
# update.txt should exist in root (created by auto-release)
if [ ! -f 'update.txt' ]; then
dolibarr_findings+=("update.txt missing in root (created by auto-release workflow)")
fi
if [ "${#dolibarr_findings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Dolibarr module checks'
printf '%s\n' '| Check | Status |'
printf '%s\n' '|---|---|'
for f in "${dolibarr_findings[@]}"; do
printf '%s\n' "| ${f} | Warning |"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
else
{
printf '%s\n' '### Dolibarr module checks'
printf '%s\n' 'All Dolibarr-specific checks passed.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
extended_enabled="${EXTENDED_CHECKS:-true}"
extended_findings=()

View File

@@ -9,36 +9,58 @@
# INGROUP: MokoStandards.Maintenance
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/repository-cleanup.yml
# VERSION: 04.01.00
# BRIEF: One-time repository cleanup — reset labels, strip issue template headers, delete old branches
# VERSION: 04.02.30
# BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes
# NOTE: Synced via bulk-repo-sync to .github/workflows/repository-cleanup.yml in all governed repos.
# Run manually via workflow_dispatch. Safe to re-run — all operations are idempotent.
# Runs on the 1st and 15th of each month at 6:00 AM UTC, and on manual dispatch.
name: Repository Cleanup
on:
schedule:
- cron: '0 6 1,15 * *'
workflow_dispatch:
inputs:
reset_labels:
description: 'Delete ALL existing labels and recreate the standard 54-label set'
description: 'Delete ALL existing labels and recreate the standard set'
type: boolean
default: false
clean_branches:
description: 'Delete old chore/sync-mokostandards-* branches'
type: boolean
default: true
clean_branches:
description: 'Delete old chore/sync-mokostandards-* branches (keeps current versioned branch only)'
clean_workflows:
description: 'Delete orphaned workflow runs (cancelled, stale)'
type: boolean
default: true
clean_logs:
description: 'Delete workflow run logs older than 30 days'
type: boolean
default: true
fix_templates:
description: 'Strip copyright comment blocks from issue templates'
type: boolean
default: true
rebuild_indexes:
description: 'Rebuild docs/ index files'
type: boolean
default: true
delete_closed_issues:
description: 'Delete issues that have been closed for more than 30 days'
type: boolean
default: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
issues: write
actions: write
jobs:
cleanup:
name: Repository Cleanup
name: Repository Maintenance
runs-on: ubuntu-latest
steps:
@@ -46,12 +68,18 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
- name: Check actor permission
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
ACTOR="${{ github.actor }}"
# Schedule triggers use github-actions[bot]
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "✅ Scheduled run — authorized"
exit 0
fi
AUTHORIZED_USERS="jmiller-moko github-actions[bot]"
for user in $AUTHORIZED_USERS; do
if [ "$ACTOR" = "$user" ]; then
@@ -66,9 +94,90 @@ jobs:
*) echo "❌ Admin or maintain required"; exit 1 ;;
esac
# ── Determine which tasks to run ─────────────────────────────────────
# On schedule: run all tasks with safe defaults (labels NOT reset)
# On dispatch: use input toggles
- name: Set task flags
id: tasks
run: |
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "reset_labels=false" >> $GITHUB_OUTPUT
echo "clean_branches=true" >> $GITHUB_OUTPUT
echo "clean_workflows=true" >> $GITHUB_OUTPUT
echo "clean_logs=true" >> $GITHUB_OUTPUT
echo "fix_templates=true" >> $GITHUB_OUTPUT
echo "rebuild_indexes=true" >> $GITHUB_OUTPUT
echo "delete_closed_issues=false" >> $GITHUB_OUTPUT
else
echo "reset_labels=${{ inputs.reset_labels }}" >> $GITHUB_OUTPUT
echo "clean_branches=${{ inputs.clean_branches }}" >> $GITHUB_OUTPUT
echo "clean_workflows=${{ inputs.clean_workflows }}" >> $GITHUB_OUTPUT
echo "clean_logs=${{ inputs.clean_logs }}" >> $GITHUB_OUTPUT
echo "fix_templates=${{ inputs.fix_templates }}" >> $GITHUB_OUTPUT
echo "rebuild_indexes=${{ inputs.rebuild_indexes }}" >> $GITHUB_OUTPUT
echo "delete_closed_issues=${{ inputs.delete_closed_issues }}" >> $GITHUB_OUTPUT
fi
# ── DELETE RETIRED WORKFLOWS (always runs) ────────────────────────────
- name: Delete retired workflow files
run: |
echo "## 🗑️ Retired Workflow Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
RETIRED=(
".github/workflows/build.yml"
".github/workflows/code-quality.yml"
".github/workflows/release-cycle.yml"
".github/workflows/release-pipeline.yml"
".github/workflows/branch-cleanup.yml"
".github/workflows/auto-update-changelog.yml"
".github/workflows/enterprise-issue-manager.yml"
".github/workflows/flush-actions-cache.yml"
".github/workflows/mokostandards-script-runner.yml"
".github/workflows/unified-ci.yml"
".github/workflows/unified-platform-testing.yml"
".github/workflows/reusable-build.yml"
".github/workflows/reusable-ci-validation.yml"
".github/workflows/reusable-deploy.yml"
".github/workflows/reusable-php-quality.yml"
".github/workflows/reusable-platform-testing.yml"
".github/workflows/reusable-project-detector.yml"
".github/workflows/reusable-release.yml"
".github/workflows/reusable-script-executor.yml"
".github/workflows/rebuild-docs-indexes.yml"
".github/workflows/setup-project-v2.yml"
".github/workflows/sync-docs-to-project.yml"
".github/workflows/release.yml"
".github/workflows/sync-changelogs.yml"
".github/workflows/version_branch.yml"
"update.json"
".github/workflows/auto-version-branch.yml"
)
DELETED=0
for wf in "${RETIRED[@]}"; do
if [ -f "$wf" ]; then
git rm "$wf" 2>/dev/null || rm -f "$wf"
echo " Deleted: \`$(basename $wf)\`" >> $GITHUB_STEP_SUMMARY
DELETED=$((DELETED+1))
fi
done
if [ "$DELETED" -gt 0 ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore: delete ${DELETED} retired workflow file(s) [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ ${DELETED} retired workflow(s) deleted" >> $GITHUB_STEP_SUMMARY
else
echo "✅ No retired workflows found" >> $GITHUB_STEP_SUMMARY
fi
# ── LABEL RESET ──────────────────────────────────────────────────────
- name: Reset labels to standard set
if: inputs.reset_labels == true
if: steps.tasks.outputs.reset_labels == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
@@ -76,23 +185,16 @@ jobs:
echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Delete all existing labels
echo "Deleting existing labels..."
DELETED=0
gh api "repos/${REPO}/labels?per_page=100" --paginate --jq '.[].name' | while read -r label; do
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$label', safe=''))")
gh api -X DELETE "repos/${REPO}/labels/${ENCODED}" --silent 2>/dev/null && DELETED=$((DELETED+1)) || true
gh api -X DELETE "repos/${REPO}/labels/${ENCODED}" --silent 2>/dev/null || true
done
echo "Deleted existing labels" >> $GITHUB_STEP_SUMMARY
# Create the standard 54-label set
echo "Creating standard labels..."
CREATED=0
while IFS='|' read -r name color description; do
[ -z "$name" ] && continue
gh api "repos/${REPO}/labels" \
-f name="$name" -f color="$color" -f description="$description" \
--silent 2>/dev/null && CREATED=$((CREATED+1)) || true
--silent 2>/dev/null || true
done << 'LABELS'
joomla|7F52FF|Joomla extension or component
dolibarr|FF6B6B|Dolibarr module or extension
@@ -125,6 +227,7 @@ jobs:
type: enhancement|84B6EB|Enhancement to existing feature
type: refactor|F9D0C4|Code refactoring
type: chore|FEF2C0|Maintenance tasks
type: version|0E8A16|Version-related change
status: pending|FBCA04|Pending action or decision
status: in-progress|0E8A16|Currently being worked on
status: blocked|B60205|Blocked by another issue or dependency
@@ -149,45 +252,85 @@ jobs:
version-drift|FFA500|Version mismatch detected
deploy-failure|CC0000|Automated deploy failure tracking
template-validation-failure|D73A4A|Template workflow validation failure
version|0E8A16|Version bump or release
LABELS
echo "✅ Standard labels created" >> $GITHUB_STEP_SUMMARY
# ── BRANCH CLEANUP ───────────────────────────────────────────────────
- name: Delete old sync branches
if: inputs.clean_branches == true
if: steps.tasks.outputs.clean_branches == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
CURRENT="chore/sync-mokostandards-v04.01.00"
CURRENT="chore/sync-mokostandards-v04.02.29"
echo "## 🌿 Branch Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
DELETED=0
FOUND=false
gh api "repos/${REPO}/branches?per_page=100" --jq '.[].name' | \
grep "^chore/sync-mokostandards" | \
grep -v "^${CURRENT}$" | while read -r branch; do
# Close any open PRs on this branch
gh pr list --repo "$REPO" --head "$branch" --state open --json number --jq '.[].number' 2>/dev/null | while read -r pr; do
gh pr close "$pr" --repo "$REPO" --comment "Superseded by \`${CURRENT}\`" 2>/dev/null || true
echo " Closed PR #${pr}" >> $GITHUB_STEP_SUMMARY
done
# Delete the branch
gh api -X DELETE "repos/${REPO}/git/refs/heads/${branch}" --silent 2>/dev/null || true
echo " Deleted: \`${branch}\`" >> $GITHUB_STEP_SUMMARY
FOUND=true
done
if [ "$FOUND" != "true" ]; then
echo "✅ No old sync branches found" >> $GITHUB_STEP_SUMMARY
fi
# ── WORKFLOW RUN CLEANUP ─────────────────────────────────────────────
- name: Clean up workflow runs
if: steps.tasks.outputs.clean_workflows == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
echo "## 🔄 Workflow Run Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
DELETED=0
# Delete cancelled and stale workflow runs
for status in cancelled stale; do
gh api "repos/${REPO}/actions/runs?status=${status}&per_page=100" \
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
gh api -X DELETE "repos/${REPO}/actions/runs/${run_id}" --silent 2>/dev/null || true
DELETED=$((DELETED+1))
done
done
echo "✅ Cleaned cancelled/stale workflow runs" >> $GITHUB_STEP_SUMMARY
# ── LOG CLEANUP ──────────────────────────────────────────────────────
- name: Delete old workflow run logs
if: steps.tasks.outputs.clean_logs == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
CUTOFF=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
echo "## 📋 Log Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Deleting logs older than: ${CUTOFF}" >> $GITHUB_STEP_SUMMARY
DELETED=0
gh api "repos/${REPO}/actions/runs?created=<${CUTOFF}&per_page=100" \
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
gh api -X DELETE "repos/${REPO}/actions/runs/${run_id}/logs" --silent 2>/dev/null || true
DELETED=$((DELETED+1))
done
if [ "$DELETED" -eq 0 ] 2>/dev/null; then
echo "✅ No old sync branches found" >> $GITHUB_STEP_SUMMARY
else
echo "✅ Cleanup complete" >> $GITHUB_STEP_SUMMARY
fi
echo "✅ Cleaned old workflow run logs" >> $GITHUB_STEP_SUMMARY
# ── ISSUE TEMPLATE FIX ──────────────────────────────────────────────
- name: Strip copyright headers from issue templates
if: inputs.fix_templates == true
if: steps.tasks.outputs.fix_templates == 'true'
run: |
echo "## 📋 Issue Template Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
@@ -214,26 +357,158 @@ jobs:
echo "✅ No templates need cleaning" >> $GITHUB_STEP_SUMMARY
fi
# ── SELF-DELETE ─────────────────────────────────────────────────────
- name: Delete this workflow (one-time use)
if: success()
# ── REBUILD DOC INDEXES ─────────────────────────────────────────────
- name: Rebuild docs/ index files
if: steps.tasks.outputs.rebuild_indexes == 'true'
run: |
echo "## 📚 Documentation Index Rebuild" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -d "docs" ]; then
echo "⏭️ No docs/ directory — skipping" >> $GITHUB_STEP_SUMMARY
exit 0
fi
UPDATED=0
# Generate index.md for each docs/ subdirectory
find docs -type d | while read -r dir; do
INDEX="${dir}/index.md"
FILES=$(find "$dir" -maxdepth 1 -name "*.md" ! -name "index.md" -printf "- [%f](./%f)\n" 2>/dev/null | sort)
if [ -z "$FILES" ]; then
continue
fi
cat > "$INDEX" << INDEXEOF
# $(basename "$dir")
## Documents
${FILES}
---
*Auto-generated by repository-cleanup workflow*
INDEXEOF
# Dedent
sed -i 's/^ //' "$INDEX"
UPDATED=$((UPDATED+1))
done
if [ "$UPDATED" -gt 0 ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/
if ! git diff --cached --quiet; then
git commit -m "docs: rebuild documentation indexes [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ ${UPDATED} index file(s) rebuilt and committed" >> $GITHUB_STEP_SUMMARY
else
echo "✅ All indexes already up to date" >> $GITHUB_STEP_SUMMARY
fi
else
echo "✅ No indexes to rebuild" >> $GITHUB_STEP_SUMMARY
fi
# ── VERSION DRIFT DETECTION ──────────────────────────────────────────
- name: Check for version drift
run: |
echo "## 📦 Version Drift Check" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -f "README.md" ]; then
echo "⏭️ No README.md — skipping" >> $GITHUB_STEP_SUMMARY
exit 0
fi
README_VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md 2>/dev/null | head -1)
if [ -z "$README_VERSION" ]; then
echo "⚠️ No VERSION found in README.md FILE INFORMATION block" >> $GITHUB_STEP_SUMMARY
exit 0
fi
echo "**README version:** \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
DRIFT=0
CHECKED=0
# Check all files with FILE INFORMATION blocks
while IFS= read -r -d '' file; do
FILE_VERSION=$(grep -oP '^\s*\*?\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' "$file" 2>/dev/null | head -1)
[ -z "$FILE_VERSION" ] && continue
CHECKED=$((CHECKED+1))
if [ "$FILE_VERSION" != "$README_VERSION" ]; then
echo " ⚠️ \`${file}\`: \`${FILE_VERSION}\` (expected \`${README_VERSION}\`)" >> $GITHUB_STEP_SUMMARY
DRIFT=$((DRIFT+1))
fi
done < <(find . -maxdepth 4 -type f \( -name "*.php" -o -name "*.md" -o -name "*.yml" \) ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -print0 2>/dev/null)
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$DRIFT" -gt 0 ]; then
echo "⚠️ **${DRIFT}** file(s) out of ${CHECKED} have version drift" >> $GITHUB_STEP_SUMMARY
echo "Run \`sync-version-on-merge\` workflow or update manually" >> $GITHUB_STEP_SUMMARY
else
echo "✅ All ${CHECKED} file(s) match README version \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY
fi
# ── PROTECT CUSTOM WORKFLOWS ────────────────────────────────────────
- name: Ensure custom workflow directory exists
run: |
echo "## 🔧 Custom Workflows" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -d ".github/workflows/custom" ]; then
mkdir -p .github/workflows/custom
cat > .github/workflows/custom/README.md << 'CWEOF'
# Custom Workflows
Place repo-specific workflows here. Files in this directory are:
- **Never overwritten** by MokoStandards bulk sync
- **Never deleted** by the repository-cleanup workflow
- Safe for custom CI, notifications, or repo-specific automation
Synced workflows live in `.github/workflows/` (parent directory).
CWEOF
sed -i 's/^ //' .github/workflows/custom/README.md
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add .github/workflows/custom/
if ! git diff --cached --quiet; then
git commit -m "chore: create .github/workflows/custom/ for repo-specific workflows [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ Created \`.github/workflows/custom/\` directory" >> $GITHUB_STEP_SUMMARY
fi
else
CUSTOM_COUNT=$(find .github/workflows/custom -name "*.yml" -o -name "*.yaml" 2>/dev/null | wc -l)
echo "✅ Custom workflow directory exists (${CUSTOM_COUNT} workflow(s))" >> $GITHUB_STEP_SUMMARY
fi
# ── DELETE CLOSED ISSUES ──────────────────────────────────────────────
- name: Delete old closed issues
if: steps.tasks.outputs.delete_closed_issues == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
echo "## 🗑️ Self-Cleanup" >> $GITHUB_STEP_SUMMARY
REPO="${{ github.repository }}"
CUTOFF=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
echo "## 🗑️ Closed Issue Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Deleting issues closed before: ${CUTOFF}" >> $GITHUB_STEP_SUMMARY
WORKFLOW_FILE=".github/workflows/repository-cleanup.yml"
if [ -f "$WORKFLOW_FILE" ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git rm "$WORKFLOW_FILE"
git commit -m "chore: remove repository-cleanup.yml after successful run [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ Workflow file deleted — it will not appear in future syncs" >> $GITHUB_STEP_SUMMARY
DELETED=0
gh api "repos/${REPO}/issues?state=closed&since=1970-01-01T00:00:00Z&per_page=100&sort=updated&direction=asc" \
--jq ".[] | select(.closed_at < \"${CUTOFF}\") | .number" 2>/dev/null | while read -r num; do
# Lock and close with "not_planned" to mark as cleaned up
gh api "repos/${REPO}/issues/${num}/lock" -X PUT -f lock_reason="resolved" --silent 2>/dev/null || true
echo " Locked issue #${num}" >> $GITHUB_STEP_SUMMARY
DELETED=$((DELETED+1))
done
if [ "$DELETED" -eq 0 ] 2>/dev/null; then
echo "✅ No old closed issues found" >> $GITHUB_STEP_SUMMARY
else
echo " Workflow file already removed" >> $GITHUB_STEP_SUMMARY
echo "✅ Locked ${DELETED} old closed issue(s)" >> $GITHUB_STEP_SUMMARY
fi
- name: Summary
@@ -241,4 +516,4 @@ jobs:
run: |
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Run by @${{ github.actor }} via workflow_dispatch*" >> $GITHUB_STEP_SUMMARY
echo "*Run by @${{ github.actor }} — trigger: ${{ github.event_name }}*" >> $GITHUB_STEP_SUMMARY

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
# INGROUP: MokoStandards.Automation
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/sync-version-on-merge.yml
# VERSION: 04.01.00
# VERSION: 04.02.30
# BRIEF: Auto-bump patch version on every push to main and propagate to all file headers
# NOTE: Synced via bulk-repo-sync to .github/workflows/sync-version-on-merge.yml in all governed repos.
# README.md is the single source of truth for the repository version.
@@ -32,6 +32,9 @@ permissions:
contents: write
issues: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
sync-version:
name: Propagate README version
@@ -45,7 +48,7 @@ jobs:
fetch-depth: 0
- name: Set up PHP
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # v2.31.0
uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0
with:
php-version: '8.1'
tools: composer
@@ -55,7 +58,7 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --quiet \
git clone --depth 1 --branch version/04.02.29 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
@@ -64,31 +67,20 @@ jobs:
- name: Auto-bump patch version
if: ${{ github.event_name == 'push' && github.actor != 'github-actions[bot]' }}
run: |
# If README.md was part of this push, the author already bumped the version — skip.
if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -q '^README\.md$'; then
echo "README.md changed in this push — skipping auto-bump"
exit 0
fi
CURRENT=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1)
if [ -z "$CURRENT" ]; then
echo "⚠️ No VERSION found in README.md — skipping auto-bump"
RESULT=$(php /tmp/mokostandards/api/cli/version_bump.php --path .) || {
echo "⚠️ Could not bump version — skipping"
exit 0
fi
# Increment the patch component (zero-padded to 2 digits)
MAJOR=$(echo "$CURRENT" | cut -d. -f1)
MINOR=$(echo "$CURRENT" | cut -d. -f2)
PATCH=$(echo "$CURRENT" | cut -d. -f3)
NEW_PATCH=$(printf '%02d' $(( 10#$PATCH + 1 )))
NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
echo "Auto-bumping patch: $CURRENT → $NEW_VERSION"
sed -i "s/^\(\s*VERSION:\s*\)${CURRENT}/\1${NEW_VERSION}/" README.md
}
echo "Auto-bumping patch: $RESULT"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add README.md
git commit -m "chore(version): auto-bump patch ${CURRENT} → ${NEW_VERSION} [skip ci]" \
git commit -m "chore(version): auto-bump patch ${RESULT} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
@@ -96,7 +88,7 @@ jobs:
id: readme_version
run: |
git pull --ff-only 2>/dev/null || true
VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1)
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "⚠️ No VERSION in README.md — skipping propagation"
echo "skip=true" >> $GITHUB_OUTPUT
@@ -119,8 +111,9 @@ jobs:
- name: Commit updated files
if: ${{ steps.readme_version.outputs.skip != 'true' && inputs.dry_run != true }}
run: |
git pull --ff-only 2>/dev/null || true
if git diff --quiet; then
echo " No version changes needed"
echo " No version changes needed — already up to date"
exit 0
fi
VERSION="${{ steps.readme_version.outputs.version }}"

20
.mokostandards Normal file
View File

@@ -0,0 +1,20 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
# DEFGROUP: MokoStandards.Templates.Config
# INGROUP: MokoStandards.Templates
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/configs/moko-standards.yml
# VERSION: 04.02.30
# BRIEF: Governance attachment template — synced to .mokostandards in every governed repository
# NOTE: Tokens replaced at sync time: mokoconsulting-tech, MokoCassiopeia, waas-component, 04.02.29
#
# This file is managed automatically by MokoStandards bulk sync.
# Do not edit manually — changes will be overwritten on the next sync.
# To update governance settings, open a PR in MokoStandards instead:
# https://github.com/mokoconsulting-tech/MokoStandards
standards_source: "https://github.com/mokoconsulting-tech/MokoStandards"
standards_version: "04.02.29"
platform: "waas-component"
governed_repo: "mokoconsulting-tech/MokoCassiopeia"

View File

@@ -1,98 +1,87 @@
<!--
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License (./LICENSE.md).
# FILE INFORMATION
DEFGROUP: Joomla.Template
INGROUP: MokoCassiopeia.Governance
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
FILE: CODE_OF_CONDUCT.md
VERSION: 03.06.03
BRIEF: Contributor code of conduct for the MokoCassiopeia project.
PATH: /CODE_OF_CONDUCT.md
NOTE: This document defines behavioral expectations and enforcement processes.
DEFGROUP:
INGROUP: Project.Documentation
REPO:
VERSION: 04.02.30
PATH: ./CODE_OF_CONDUCT.md
BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default
-->
# Code of Conduct
## Code of Conduct
## 1. Purpose
This Code of Conduct establishes expectations for behavior within the MokoCassiopeia project community. The objective is to maintain a professional, inclusive, and respectful environment aligned with open source governance best practices.
The purpose of this Code of Conduct is to ensure a safe, inclusive, and respectful environment for all contributors and participants in Moko Consulting projects. This applies to all interactions, whether in repositories, issue trackers, documentation, meetings, or community spaces.
## Scope
## 2. Our Standards
This Code of Conduct applies to all project spaces, including:
Participants are expected to uphold behaviors that strengthen our community, including:
* GitHub repositories, issues, pull requests, discussions, and security advisories.
* Project documentation, workflows, and release processes.
* Any communication channels officially associated with the project.
Demonstrating empathy and respect toward others.
Being inclusive of diverse viewpoints and backgrounds.
Gracefully accepting constructive feedback.
Prioritizing collaboration over conflict.
Showing professionalism in all interactions.
## Our Standards
### Unacceptable behavior includes:
Participants are expected to:
Harassment, discrimination, or derogatory comments.
Threatening or violent language or actions.
Disruptive, aggressive, or intentionally harmful behavior.
Publishing others private information without permission.
Any behavior that violates applicable laws.
* Communicate professionally and respectfully.
* Provide constructive feedback focused on technical merit and project objectives.
* Respect differing viewpoints, experience levels, and backgrounds.
* Follow documented contribution, security, and governance policies.
## 3. Responsibilities of Maintainers
Unacceptable behavior includes:
Maintainers are responsible for:
* Harassment, discrimination, or exclusionary conduct.
* Personal attacks, insults, or inflammatory comments.
* Publishing private information without consent.
* Disruptive behavior that materially interferes with project operations.
Clarifying acceptable behavior.
Taking appropriate corrective action when unacceptable behavior occurs.
Removing, editing, or rejecting contributions that violate this Code.
Temporarily or permanently banning contributors who engage in repeated or severe violations.
## Enforcement Responsibilities
## 4. Scope
Project maintainers are responsible for:
This Code applies to:
* Clarifying standards when questions arise.
* Taking appropriate and proportionate corrective action when violations occur.
* Maintaining confidentiality to the extent practical during investigations.
All Moko Consulting repositories.
All documentation and collaboration platforms.
Public and private communication related to project activities.
Any representation of Moko Consulting in online or offline spaces.
## Reporting
## 5. Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported through:
Instances of misconduct may be reported to:
**[hello@mokoconsulting.tech](mailto:hello@mokoconsulting.tech)**
* Email: `hello@mokoconsulting.tech` with subject `CODE OF CONDUCT: MokoCassiopeia`.
All reports will be reviewed and investigated promptly and fairly. Maintainers are obligated to maintain confidentiality where possible.
Reports should include relevant context, links, screenshots, or other supporting information.
Consequences may include:
## Enforcement Guidelines
A warning.
Required training or mediation.
Temporary or permanent bans.
Escalation to legal authorities when required.
Corrective actions may include, but are not limited to:
## 6. Acknowledgements
* Private warning or request for corrective action.
* Temporary or permanent restriction from project participation.
* Removal of content that violates this Code of Conduct.
This Code of Conduct is inspired by widely adopted community guidelines, including the Contributor Covenant and major open-source collaboration standards.
Decisions are made based on impact, severity, and pattern of behavior.
## 7. Related Documents
## No Retaliation
[Governance Guide](./docs-governance.md)
[Contributor Guide](./docs-contributing.md)
[Documentation Index](./docs-index.md)
Retaliation against individuals who report concerns in good faith is not tolerated. Any retaliatory behavior will be treated as a separate violation.
## Jurisdiction
This project is managed from Tennessee, USA. This statement is informational and does not constitute legal advice.
---
## Metadata
* **Document:** CODE_OF_CONDUCT.md
* **Repository:** [https://github.com/mokoconsulting-tech/MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia)
* **Path:** /CODE_OF_CONDUCT.md
* **Owner:** Moko Consulting
* **Version:** 03.06.00
* **Status:** Active
* **Effective Date:** 2025-12-18
* **Last Reviewed:** 2025-12-18
## Revision History
| Date | Change Summary | Author |
| ---------- | ----------------------------------------------------------------------------- | --------------- |
| 2025-12-18 | Initial publication of contributor conduct standards and enforcement process. | Moko Consulting |
This Code of Conduct is a living document and may be updated following the established Change Management process.

View File

@@ -1,145 +1,55 @@
<!--
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License (./LICENSE).
# FILE INFORMATION
DEFGROUP: Joomla.Template
INGROUP: MokoCassiopeia.Governance
DEFGROUP: {{DEFGROUP}}
INGROUP: Project.Documentation
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
FILE: CONTRIBUTING.md
VERSION: 03.06.03
BRIEF: Contribution guidelines for the MokoCassiopeia project.
PATH: /CONTRIBUTING.md
NOTE: This document defines contribution workflow, standards, and governance alignment.
-->
VERSION: 04.02.29
PATH: ./CONTRIBUTING.md
BRIEF: How to contribute; commit, PR, testing and security policies
-->
## Contributing
# Contributing
This document defines how to contribute to the MokoCassiopeia project. The goal is to ensure changes are reviewable, auditable, and aligned with project governance and release processes.
Thank you for your interest in contributing to this project!
## Scope
This repository is governed by **[MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)** — the authoritative source of coding standards, workflows, and policies for all Moko Consulting repositories.
These guidelines apply to all contributions, including:
## Quick Start
* Source code changes
* Documentation updates
* Bug reports and enhancement proposals
1. **Fork** the repository
2. **Branch** from `main` using `dev/XX.YY.ZZ/description` format
3. **Follow** [MokoStandards coding conventions](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md)
4. **Commit** using [conventional commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `docs:`, `chore:`, etc.
5. **Open a PR** targeting `main` — squash merge only
## Prerequisites
## Standards
Contributors are expected to:
All contributions must follow MokoStandards:
* Have a working understanding of Joomla template structure.
* Be familiar with Git and GitHub pull request workflows.
* Review repository governance documents prior to submitting changes.
* Set up the development environment using the provided tools.
| Standard | Reference |
|----------|-----------|
| Coding Style | [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) |
| File Headers | [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) |
| Branching | [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) |
| Merge Strategy | [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) |
| Scripting | [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) |
### Quick Setup
## Version Bumping
For first-time contributors:
```bash
# Clone the repository
git clone https://github.com/mokoconsulting-tech/MokoCassiopeia.git
cd MokoCassiopeia
```
See [docs/QUICK_START.md](./docs/QUICK_START.md) for detailed setup instructions.
## Development Tools
The repository provides several tools to streamline development:
* **Pre-commit Hooks**: Automatic local validation before commits
## Contribution Workflow
1. Fork the repository.
2. Create a branch from the active development branch.
3. Make focused, minimal changes that address a single concern.
4. Submit a pull request with a clear description of intent and impact.
Direct commits to protected branches are not permitted.
## Branching and Versioning
* Development work occurs on designated development branches.
* Releases are produced from versioned branches following repository standards.
* Contributors should not bump version numbers unless explicitly requested.
## Coding and Formatting Standards
All contributions must:
* Follow Joomla coding standards where applicable.
* Conform to Moko Consulting repository standards for headers, metadata, and file structure.
* Avoid introducing tabs, inconsistent path separators, or non portable assumptions.
Automated checks may reject changes that do not meet these requirements.
## Documentation Standards
Documentation changes must:
* Include required metadata and revision history sections.
* Avoid embedding version numbers in revision history tables.
* Preserve existing structure unless a structural change is explicitly proposed.
## Commit Messages
Commit messages should:
* Be concise and descriptive.
* Focus on what changed and why.
* Avoid referencing internal issue trackers unless required.
## Reporting Issues
Bug reports and enhancement requests should be filed as GitHub issues and include:
* Clear reproduction steps or use cases.
* Expected versus actual behavior.
* Relevant environment details.
Security related issues must follow the process defined in SECURITY.md and must not be reported publicly.
## Review Process
All pull requests are subject to review. Review criteria include:
* Technical correctness
* Alignment with project goals
* Maintainability and clarity
* Risk introduced to release and update processes
Maintainers may request changes prior to approval.
Every PR must bump the patch version in `README.md`. The `sync-version-on-merge` workflow propagates it to all file headers automatically on merge to `main`.
## License
By contributing, you agree that your contributions will be licensed under GPL-3.0-or-later, consistent with the rest of the project.
## Code of Conduct
Participation in this project is governed by the Code of Conduct. Unacceptable behavior may result in contribution restrictions.
---
## Metadata
* **Document:** CONTRIBUTING.md
* **Repository:** [https://github.com/mokoconsulting-tech/MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia)
* **Path:** /CONTRIBUTING.md
* **Owner:** Moko Consulting
* **Version:** 03.06.00
* **Status:** Active
* **Effective Date:** 2025-12-18
* **Last Reviewed:** 2025-12-18
## Revision History
| Date | Change Summary | Author |
| ---------- | ------------------------------------------------------------------------- | --------------- |
| 2025-12-18 | Initial publication of contribution guidelines and workflow expectations. | Moko Consulting |
By contributing, you agree that your contributions will be licensed under the [GPL-3.0-or-later](LICENSE) license.

View File

@@ -1,185 +1,240 @@
<!--
Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
DEFGROUP: Joomla.Template
INGROUP: MokoCassiopeia.Governance
REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia
FILE: SECURITY.md
VERSION: 03.06.02
BRIEF: Security policy and vulnerability reporting process for MokoCassiopeia.
PATH: /SECURITY.md
NOTE: This policy is process oriented and does not replace secure engineering practices.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
# FILE INFORMATION
DEFGROUP: [PROJECT_NAME]
INGROUP: [PROJECT_NAME].Documentation
REPO: [REPOSITORY_URL]
PATH: /SECURITY.md
VERSION: 04.02.30
BRIEF: Security vulnerability reporting and handling policy
-->
## Security Policy
# Security Policy
This document defines how MokoCassiopeia handles vulnerability intake, triage, remediation, and disclosure. The objective is to reduce risk, protect downstream users, and preserve operational continuity with a verifiable audit trail.
## Purpose and Scope
## Scope
This policy applies to:
* Repository source code, workflows, scripts, and build artifacts.
* Release packaging (ZIP outputs) generated from the repository.
* Configuration and metadata used for distribution (for example manifests and update metadata).
Out of scope:
* Vulnerabilities in upstream Joomla core, third party extensions, or external infrastructure not controlled by this repository.
* Issues that require physical access to a host, compromised administrator credentials, or a compromised hosting provider, unless the repository materially increases impact.
This document defines the security vulnerability reporting, response, and disclosure policy for [PROJECT_NAME] and all repositories governed by these standards. It establishes the authoritative process for responsible disclosure, assessment, remediation, and communication of security issues.
## Supported Versions
Security fixes are prioritized for:
Security updates are provided for the following versions:
* The latest released version.
* The current development line when it is actively used for release engineering.
| Version | Supported |
| ------- | ------------------ |
| [X.x.x] | :white_check_mark: |
| < [X.0] | :x: |
Backports may be provided based on impact, deployment footprint, and engineering capacity.
Only the current major version receives security updates. Users should upgrade to the latest supported version to receive security patches.
## Reporting a Vulnerability
Use one of the following channels:
### Where to Report
* GitHub Security Advisories (preferred): use the repository security tab to submit a private report.
* Email: send details to `hello@mokoconsulting.tech` with subject `SECURITY: MokoCassiopeia vulnerability report`.
**DO NOT** create public GitHub issues for security vulnerabilities.
Do not file a public GitHub issue for suspected security vulnerabilities.
Report security vulnerabilities privately to:
### What to include
**Email**: `security@[DOMAIN]`
Provide enough detail to reproduce and triage:
**Subject Line**: `[SECURITY] Brief Description`
* A clear description of the vulnerability and expected impact.
* A minimal proof of concept or reproduction steps.
* Affected versions, configuration assumptions, and environment details.
* Any proposed mitigation or patch.
* Your preferred contact details for follow up.
### What to Include
## Triage and Response Targets
A complete vulnerability report should include:
The project operates with response targets aligned to practical delivery realities:
1. **Description**: Clear explanation of the vulnerability
2. **Impact**: Potential security impact and severity assessment
3. **Affected Versions**: Which versions are vulnerable
4. **Reproduction Steps**: Detailed steps to reproduce the issue
5. **Proof of Concept**: Code, configuration, or demonstration (if applicable)
6. **Suggested Fix**: Proposed remediation (if known)
7. **Disclosure Timeline**: Your expectations for public disclosure
* **Acknowledgement:** within 3 business days.
* **Initial triage:** within 10 business days.
* **Fix plan:** communicated once severity is confirmed.
### Response Timeline
These targets are not guarantees. Complex issues, supply chain considerations, and coordination with upstream vendors may extend timelines.
* **Initial Response**: Within 3 business days
* **Assessment Complete**: Within 7 business days
* **Fix Timeline**: Depends on severity (see below)
* **Disclosure**: Coordinated with reporter
## Severity Assessment
## Severity Classification
Issues are triaged based on business impact and technical exploitability, including:
Vulnerabilities are classified using the following severity levels:
* Remote exploitability and required privileges.
* Data confidentiality, integrity, and availability impact.
* Likelihood of exploitation in typical Joomla deployments.
* Exposure surface (public endpoints, administrator area, installation flows, and update mechanisms).
### Critical
* Remote code execution
* Authentication bypass
* Data breach or exposure of sensitive information
* **Fix Timeline**: 7 days
When appropriate, industry standard scoring such as CVSS may be used for internal prioritization.
### High
* Privilege escalation
* SQL injection or command injection
* Cross-site scripting (XSS) with significant impact
* **Fix Timeline**: 14 days
## Coordinated Disclosure
### Medium
* Information disclosure (limited scope)
* Denial of service
* Security misconfigurations with moderate impact
* **Fix Timeline**: 30 days
The project follows coordinated vulnerability disclosure:
### Low
* Security best practice violations
* Minor information leaks
* Issues requiring user interaction or complex preconditions
* **Fix Timeline**: 60 days or next release
* Reports are treated as confidential until remediation is available.
* A public advisory may be published once a fix is released.
* A reasonable embargo period is expected to enable patch distribution.
## Remediation Process
If you believe disclosure is time sensitive due to active exploitation, include that assessment and any supporting indicators.
1. **Acknowledgment**: Security team confirms receipt and begins investigation
2. **Assessment**: Vulnerability is validated, severity assigned, and impact analyzed
3. **Development**: Security patch is developed and tested
4. **Review**: Patch undergoes security review and validation
5. **Release**: Fixed version is released with security advisory
6. **Disclosure**: Public disclosure follows coordinated timeline
## Security Updates and Advisories
## Security Advisories
Security updates are distributed through:
Security advisories are published via:
* GitHub releases for the repository.
* GitHub Security Advisories when applicable.
* GitHub Security Advisories
* Release notes and CHANGELOG.md
* Security mailing list (when established)
Advisories may include:
Advisories include:
* Affected versions and fixed versions.
* Mitigations and workarounds when a fix is not immediately available.
* Upgrade guidance.
* CVE identifier (if applicable)
* Severity rating
* Affected versions
* Fixed versions
* Mitigation steps
* Attribution (with reporter consent)
## Dependencies and Supply Chain Controls
## Security Best Practices
The project aims to manage supply chain risk through:
For repositories adopting MokoStandards:
* Pinning and review of workflow dependencies where feasible.
* Minimizing privileged GitHub token permissions.
* Validating build inputs prior to packaging releases.
### Required Controls
If you identify a supply chain issue (for example compromised action, dependency confusion, or malicious upstream artifact), report it as a vulnerability.
* Enable GitHub security features (Dependabot, code scanning)
* Implement branch protection on `main`
* Require code review for all changes
* Enforce signed commits (recommended)
* Use secrets management (never commit credentials)
* Maintain security documentation
* Follow secure coding standards defined in `/docs/policy/`
## Secure Development and CI Expectations
### CI/CD Security
Security posture is reinforced through operational controls:
* Validate all inputs
* Sanitize outputs
* Use least privilege access
* Pin dependencies with hash verification
* Scan for vulnerabilities in dependencies
* Audit third-party actions and tools
* CI validation for packaging inputs and manifest integrity.
* Consistent path normalization and whitespace hygiene checks where required for release correctness.
* Least privilege for GitHub Actions permissions.
#### Automated Security Scanning
### Template Security Features
All repositories MUST implement:
**Custom Head Content Injection**
**CodeQL Analysis**:
* Enabled for all supported languages (Python, JavaScript, TypeScript, Java, C/C++, C#, Go, Ruby)
* Runs on: push to main, pull requests, weekly schedule
* Query sets: `security-extended` and `security-and-quality`
* Configuration: `.github/workflows/codeql-analysis.yml`
The template provides Custom Head Code fields (`custom_head_start` and `custom_head_end`) that allow administrators to inject custom HTML, CSS, and JavaScript code. This is an intentional feature for:
**Dependabot Security Updates**:
* Weekly scans for vulnerable dependencies
* Automated pull requests for security patches
* Configuration: `.github/dependabot.yml`
* Adding analytics scripts (Google Analytics, Google Tag Manager)
* Custom meta tags
* Third-party integrations
* Custom styling
**Secret Scanning**:
* Enabled by default with push protection
* Prevents accidental credential commits
* Partner patterns enabled
**Security Considerations:**
**Dependency Review**:
* Required for all pull requests
* Blocks introduction of known vulnerable dependencies
* Automatic license compliance checking
* These fields use `filter="raw"` to allow HTML/JS injection
* **Access is restricted to Joomla administrators only** via template configuration
* This is not an XSS vulnerability as it requires administrator privileges
* Administrators should only add trusted code from verified sources
* Regular security audits should review custom head content
See [Security Scanning Policy](docs/policy/security-scanning.md) for detailed requirements.
This policy does not guarantee that all vulnerabilities will be prevented. It defines how risk is managed when issues are discovered.
### Dependency Management
## Safe Harbor
* Keep dependencies up to date
* Monitor security advisories for dependencies
* Remove unused dependencies
* Audit new dependencies before adoption
* Document security-critical dependencies
The project supports good faith security research. When you:
## Compliance and Governance
* Avoid privacy violations, data destruction, and service disruption.
* Limit testing to systems you own or have explicit permission to test.
* Provide a reasonable window for coordinated disclosure.
This security policy is binding for all repositories governed by MokoStandards. Deviations require documented justification and approval from the Security Owner.
Then the project will treat your report as a constructive security contribution.
Security policies are reviewed and updated at least annually or following significant security incidents.
Jurisdiction note: this repository is managed from Tennessee, USA. This note is informational only and does not constitute legal advice.
## Attribution and Recognition
## Public Communications
We acknowledge and appreciate responsible disclosure. With your permission, we will:
Only maintainers will publish security advisories or public statements for confirmed vulnerabilities. Public communication will focus on actionable remediation and operational risk reduction.
* Credit you in security advisories
* List you in CHANGELOG.md for the fix release
* Recognize your contribution publicly (if desired)
## Acknowledgements
## Contact and Escalation
If you want credit, include the name or handle to list in an advisory. If you prefer anonymity, state that explicitly.
* **Security Team**: security@[DOMAIN]
* **Primary Contact**: [CONTACT_EMAIL]
* **Escalation**: For urgent matters requiring immediate attention, contact the maintainer directly via GitHub
## Out of Scope
The following are explicitly out of scope:
* Issues in third-party dependencies (report directly to maintainers)
* Social engineering attacks
* Physical security issues
* Denial of service via resource exhaustion without amplification
* Issues requiring physical access to systems
* Theoretical vulnerabilities without proof of exploitability
---
## Metadata
* **Document:** SECURITY.md
* **Repository:** [https://github.com/mokoconsulting-tech/MokoCassiopeia](https://github.com/mokoconsulting-tech/MokoCassiopeia)
* **Path:** /SECURITY.md
* **Owner:** Moko Consulting
* **Version:** 03.06.00
* **Status:** Active
* **Effective Date:** 2025-12-18
* **Last Reviewed:** 2025-12-18
| Field | Value |
| ------------ | ----------------------------------------------- |
| Document | Security Policy |
| Path | /SECURITY.md |
| Repository | [REPOSITORY_URL] |
| Owner | [OWNER_NAME] |
| Scope | Security vulnerability handling |
| Applies To | All repositories governed by MokoStandards |
| Status | Active |
| Effective | [YYYY-MM-DD] |
## Revision History
| Date | Change Summary | Author |
| ---------- | ------------------------------------------------------------------------------------------------ | --------------- |
| 2026-01-30 | Added Template Security Features section documenting custom head content injection controls. | Copilot Agent |
| 2025-12-18 | Initial publication of security policy, intake channels, triage targets, and disclosure process. | Moko Consulting |
| Date | Change Description | Author |
| ---------- | ------------------------------------------------- | --------------- |
| [YYYY-MM-DD] | Initial creation | [AUTHOR_NAME] |

View File

@@ -14,7 +14,7 @@
"prefer-stable": true,
"require": {
"php": ">=8.1",
"mokoconsulting-tech/enterprise": "^4.0"
"mokoconsulting-tech/enterprise": "dev-version/04.02.00"
},
"require-dev": {
"phpunit/phpunit": "^10.5",