diff --git a/.gitea/.mokostandards b/.gitea/.mokostandards new file mode 100644 index 0000000..5899fe8 --- /dev/null +++ b/.gitea/.mokostandards @@ -0,0 +1,78 @@ + + + + + joomla-api-mcp + MokoConsulting + MCP server for Joomla Web Services API operations + GNU General Public License v3 + + + waas-component + 04.07.00 + https://git.mokoconsulting.tech/MokoConsulting/MokoStandards + 2026-05-02T23:06:09+00:00 + + + Markdown + joomla-extension + + + + ${{ secrets.DEV_HOST }} + ${{ secrets.DEV_PATH }} + sftp + dev/** + src/ + + + ${{ secrets.DEMO_HOST }} + ${{ secrets.DEMO_PATH }} + sftp + main + src/ + + + + + + + + + + + + diff --git a/.github/workflows/auto-assign.yml b/.gitea/workflows/auto-assign.yml similarity index 95% rename from .github/workflows/auto-assign.yml rename to .gitea/workflows/auto-assign.yml index d0b70f6..1996c1c 100644 --- a/.github/workflows/auto-assign.yml +++ b/.gitea/workflows/auto-assign.yml @@ -7,7 +7,7 @@ # REPO: https://github.com/mokoconsulting-tech/MokoStandards # PATH: /.github/workflows/auto-assign.yml # VERSION: 04.06.00 -# BRIEF: Auto-assign jmiller-moko to unassigned issues and PRs every 15 minutes +# BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes name: Auto-Assign Issues & PRs @@ -35,7 +35,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} run: | REPO="${{ github.repository }}" - ASSIGNEE="jmiller-moko" + ASSIGNEE="jmiller" echo "## ๐Ÿท๏ธ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/auto-dev-issue.yml b/.gitea/workflows/auto-dev-issue.yml similarity index 99% rename from .github/workflows/auto-dev-issue.yml rename to .gitea/workflows/auto-dev-issue.yml index 9b5fbe2..f61e1fc 100644 --- a/.github/workflows/auto-dev-issue.yml +++ b/.gitea/workflows/auto-dev-issue.yml @@ -135,7 +135,7 @@ jobs: --title "$SUB_FULL_TITLE" \ --body "$SUB_BODY" \ --label "${SUB_LABELS}" \ - --assignee "jmiller-moko" 2>&1) + --assignee "jmiller" 2>&1) SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$') if [ -n "$SUB_NUM" ]; then @@ -154,7 +154,7 @@ jobs: --title "$TITLE" \ --body "$PARENT_BODY" \ --label "${LABEL_TYPE},version" \ - --assignee "jmiller-moko" 2>&1) + --assignee "jmiller" 2>&1) PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$') diff --git a/.github/workflows/auto-release.yml b/.gitea/workflows/auto-release.yml similarity index 100% rename from .github/workflows/auto-release.yml rename to .gitea/workflows/auto-release.yml diff --git a/.gitea/workflows/cascade-dev.yml b/.gitea/workflows/cascade-dev.yml new file mode 100644 index 0000000..54f9c37 --- /dev/null +++ b/.gitea/workflows/cascade-dev.yml @@ -0,0 +1,184 @@ +# Copyright (C) 2026 Moko Consulting +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# FILE INFORMATION +# DEFGROUP: Gitea.Workflow +# INGROUP: MokoStandards.Maintenance +# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API +# PATH: /templates/workflows/cascade-dev.yml.template +# VERSION: 01.00.00 +# BRIEF: Forward-merge main โ†’ dev after every push to main +# +# +========================================================================+ +# | CASCADE MAIN โ†’ DEV | +# +========================================================================+ +# | | +# | Triggers on every push to main (PR merges, bot commits, etc.) | +# | | +# | 1. Check if a 'dev' branch exists | +# | 2. Create a PR (main โ†’ dev) via Gitea API | +# | 3. Auto-merge if clean; leave open for manual resolution on conflict | +# | | +# +========================================================================+ + +name: Cascade Main โ†’ Dev + +on: + push: + branches: + - main + workflow_dispatch: + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }} + GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }} + +permissions: + contents: write + pull-requests: write + +jobs: + cascade: + name: Merge main โ†’ dev + runs-on: ubuntu-latest + if: >- + !contains(github.event.head_commit.message, '[skip ci]') && + !contains(github.event.head_commit.message, '[skip cascade]') + + steps: + - name: Check dev branch exists + id: check + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + run: | + API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + + STATUS=$(curl -sS -o /dev/null -w "%{http_code}" \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/branches/dev") + + if [ "$STATUS" = "200" ]; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "โœ… dev branch exists" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + echo "โ„น๏ธ No dev branch found (HTTP ${STATUS}) โ€” skipping cascade" + fi + + - name: Check if dev is already up to date + if: steps.check.outputs.exists == 'true' + id: diff + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + run: | + API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + + # Compare main..dev โ€” if ahead_by is 0 there's nothing to cascade + RESPONSE=$(curl -sS \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/compare/dev...main") + + AHEAD=$(echo "$RESPONSE" | jq '.total_commits // 0') + + if [ "$AHEAD" -eq 0 ]; then + echo "needs_merge=false" >> "$GITHUB_OUTPUT" + echo "โœ… dev is already up to date with main" + else + echo "needs_merge=true" >> "$GITHUB_OUTPUT" + echo "โ„น๏ธ main is ${AHEAD} commit(s) ahead of dev" + fi + + - name: Create cascade PR + if: steps.diff.outputs.needs_merge == 'true' + id: pr + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + run: | + API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + SHORT_SHA="${GITHUB_SHA:0:7}" + + # Check if a cascade PR already exists (main โ†’ dev) + EXISTING=$(curl -sS \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/pulls?state=open&head=${GITEA_ORG}:main&base=dev&limit=1") + + EXISTING_COUNT=$(echo "$EXISTING" | jq 'length') + + if [ "$EXISTING_COUNT" -gt 0 ]; then + PR_NUMBER=$(echo "$EXISTING" | jq -r '.[0].number') + PR_URL=$(echo "$EXISTING" | jq -r '.[0].html_url') + echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT" + echo "pr_exists=true" >> "$GITHUB_OUTPUT" + echo "โ„น๏ธ Cascade PR already exists: ${PR_URL}" + else + RESPONSE=$(curl -sS -w "\n%{http_code}" \ + -X POST \ + -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"title\": \"chore: cascade main โ†’ dev (${SHORT_SHA}) [skip ci]\", + \"body\": \"## Automatic cascade\n\nForward-merging \`main\` (${SHORT_SHA}) into \`dev\` to keep branches in sync.\n\nIf this PR has conflicts, please resolve them manually and merge.\n\n> Auto-created by the **Cascade Main โ†’ Dev** workflow.\", + \"head\": \"main\", + \"base\": \"dev\" + }" \ + "${API}/pulls") + + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | sed '$d') + PR_NUMBER=$(echo "$BODY" | jq -r '.number // empty') + PR_URL=$(echo "$BODY" | jq -r '.html_url // empty') + + if [ "$HTTP_CODE" = "201" ] && [ -n "$PR_NUMBER" ]; then + echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT" + echo "pr_exists=false" >> "$GITHUB_OUTPUT" + echo "โœ… Created cascade PR #${PR_NUMBER}: ${PR_URL}" + else + echo "โŒ Failed to create PR (HTTP ${HTTP_CODE}): ${BODY}" + exit 1 + fi + fi + + - name: Auto-merge cascade PR + if: steps.pr.outputs.pr_number != '' + env: + GA_TOKEN: ${{ secrets.GA_TOKEN }} + run: | + API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" + PR_NUMBER="${{ steps.pr.outputs.pr_number }}" + + # Check if PR is mergeable + PR_DATA=$(curl -sS \ + -H "Authorization: token ${GA_TOKEN}" \ + "${API}/pulls/${PR_NUMBER}") + + MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable // false') + + if [ "$MERGEABLE" != "true" ]; then + echo "โš ๏ธ PR #${PR_NUMBER} has conflicts โ€” leaving open for manual resolution" + exit 0 + fi + + # Merge the PR + RESPONSE=$(curl -sS -w "\n%{http_code}" \ + -X POST \ + -H "Authorization: token ${GA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{ + \"Do\": \"merge\", + \"merge_message_field\": \"chore: cascade main โ†’ dev [skip ci]\", + \"delete_branch_after_merge\": false + }" \ + "${API}/pulls/${PR_NUMBER}/merge") + + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + + if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "204" ]; then + echo "โœ… Cascade PR #${PR_NUMBER} merged โ€” dev is now in sync with main" + else + BODY=$(echo "$RESPONSE" | sed '$d') + echo "โš ๏ธ Merge failed (HTTP ${HTTP_CODE}): ${BODY}" + echo "PR #${PR_NUMBER} left open for manual resolution" + fi diff --git a/.github/workflows/changelog-validation.yml b/.gitea/workflows/changelog-validation.yml similarity index 100% rename from .github/workflows/changelog-validation.yml rename to .gitea/workflows/changelog-validation.yml diff --git a/.github/workflows/codeql-analysis.yml b/.gitea/workflows/codeql-analysis.yml similarity index 100% rename from .github/workflows/codeql-analysis.yml rename to .gitea/workflows/codeql-analysis.yml diff --git a/.github/workflows/copilot-agent.yml b/.gitea/workflows/copilot-agent.yml similarity index 100% rename from .github/workflows/copilot-agent.yml rename to .gitea/workflows/copilot-agent.yml diff --git a/.github/workflows/deploy-demo.yml b/.gitea/workflows/deploy-demo.yml similarity index 99% rename from .github/workflows/deploy-demo.yml rename to .gitea/workflows/deploy-demo.yml index f5fac4a..206d178 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.gitea/workflows/deploy-demo.yml @@ -94,7 +94,7 @@ jobs: AUTHORIZED="false" # Hardcoded authorized users โ€” always allowed to deploy - AUTHORIZED_USERS="jmiller-moko github-actions[bot]" + AUTHORIZED_USERS="jmiller github-actions[bot]" for user in $AUTHORIZED_USERS; do if [ "$ACTOR" = "$user" ]; then AUTHORIZED="true" @@ -704,7 +704,7 @@ jobs: --title "$TITLE" \ --body "$BODY" \ --label "$LABEL" \ - --assignee "jmiller-moko" \ + --assignee "jmiller" \ | tee -a "$GITHUB_STEP_SUMMARY" fi diff --git a/.github/workflows/deploy-dev.yml b/.gitea/workflows/deploy-dev.yml similarity index 99% rename from .github/workflows/deploy-dev.yml rename to .gitea/workflows/deploy-dev.yml index 7781d00..1814ea0 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.gitea/workflows/deploy-dev.yml @@ -99,7 +99,7 @@ jobs: AUTHORIZED="false" # Hardcoded authorized users โ€” always allowed to deploy - AUTHORIZED_USERS="jmiller-moko github-actions[bot]" + AUTHORIZED_USERS="jmiller github-actions[bot]" for user in $AUTHORIZED_USERS; do if [ "$ACTOR" = "$user" ]; then AUTHORIZED="true" diff --git a/.github/workflows/enterprise-firewall-setup.yml b/.gitea/workflows/enterprise-firewall-setup.yml similarity index 100% rename from .github/workflows/enterprise-firewall-setup.yml rename to .gitea/workflows/enterprise-firewall-setup.yml diff --git a/.github/workflows/repository-cleanup.yml b/.gitea/workflows/repository-cleanup.yml similarity index 99% rename from .github/workflows/repository-cleanup.yml rename to .gitea/workflows/repository-cleanup.yml index ea9219d..96c2a8c 100644 --- a/.github/workflows/repository-cleanup.yml +++ b/.gitea/workflows/repository-cleanup.yml @@ -80,7 +80,7 @@ jobs: echo "โœ… Scheduled run โ€” authorized" exit 0 fi - AUTHORIZED_USERS="jmiller-moko github-actions[bot]" + AUTHORIZED_USERS="jmiller github-actions[bot]" for user in $AUTHORIZED_USERS; do if [ "$ACTOR" = "$user" ]; then echo "โœ… ${ACTOR} authorized" diff --git a/.github/workflows/standards-compliance.yml b/.gitea/workflows/standards-compliance.yml similarity index 99% rename from .github/workflows/standards-compliance.yml rename to .gitea/workflows/standards-compliance.yml index 79aaedd..44ab47d 100644 --- a/.github/workflows/standards-compliance.yml +++ b/.gitea/workflows/standards-compliance.yml @@ -2601,7 +2601,7 @@ jobs: echo "Updated issue #${EXISTING}" else gh issue create --repo "$REPO" --title "$TITLE" --body "$BODY" \ - --label "$LABEL" --assignee "jmiller-moko" + --label "$LABEL" --assignee "jmiller" fi # CUSTOMIZATION: diff --git a/.github/workflows/sync-version-on-merge.yml b/.gitea/workflows/sync-version-on-merge.yml similarity index 100% rename from .github/workflows/sync-version-on-merge.yml rename to .gitea/workflows/sync-version-on-merge.yml diff --git a/.github/CLAUDE.md b/.github/CLAUDE.md deleted file mode 100644 index 667c3b4..0000000 --- a/.github/CLAUDE.md +++ /dev/null @@ -1,309 +0,0 @@ - - -> [!IMPORTANT] -> **๐Ÿ”ง AI Self-Update Required on First Use** -> -> This file may contain unfilled `{{TOKEN}}` placeholders. The MokoStandards bulk-sync system -> replaces them automatically at sync time; if you can still see them, sync has not yet run for -> this repository โ€” or this is a brand-new repo. -> -> **On your very first interaction in this repository, before answering any other question:** -> -> 1. Check whether any `{{TOKEN}}` placeholders remain in this file. -> 2. If they do, locate the values as described in the table below and replace every occurrence -> in **both** `.github/copilot-instructions.md` and `.github/CLAUDE.md`. -> 3. After replacing all tokens, **delete this entire notice block** (from `> [!IMPORTANT]` -> through the closing `> ---` line) in both files. -> 4. Tell the developer: *"I've self-updated the AI context files with this repository's -> values โ€” all set."* -> -> | Placeholder | Where to find the value | -> |---|---| -> | `MokoStandards-Template-Generic` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | -> | `https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | -> | `PHP` | The dominant programming language (check file extensions in the repository) | -> | `Generic project` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. โ€” infer from repo structure | -> -> --- - -# MokoStandards-Template-Generic โ€” GitHub Copilot Custom Instructions - -## What This Repo Is - -This is a **Moko Consulting** repository governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync. - -Repository URL: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic -Primary language: **PHP** -Platform type: **Generic project** - ---- - -## Primary Language - -**PHP is the primary language for this repository.** Follow the conventions documented in [MokoStandards coding-style-guide](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md). - -YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`. - ---- - -## File Header โ€” Always Required on New Files - -Every new file needs a copyright header as its first content. Use the minimal form unless the file is a policy doc, README, or public API. - -**PHP:** -```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: MokoStandards-Template-Generic.Module - * INGROUP: MokoStandards-Template-Generic - * REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - -declare(strict_types=1); -``` - -**Markdown:** -```markdown - -``` - -**YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - ---- - -## Version Management - -**`README.md` is the single source of truth for the repository version.** - -- **Bump the patch version on every PR** โ€” increment `XX.YY.ZZ` (e.g. `01.02.03` โ†’ `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. -- The `VERSION: XX.YY.ZZ` field in the README.md `FILE INFORMATION` block governs all other version references. -- Update the version in `README.md` only โ€” the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. -- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `04.00.04`). -- Never hardcode a specific version in document body text โ€” use the badge or FILE INFORMATION header only. - ---- - -## GitHub Actions โ€” Token Usage - -Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). This applies to all `actions/checkout`, `gh` CLI calls, and any step that talks to the GitHub API. - -```yaml -# โœ… Correct -- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - token: ${{ secrets.GH_TOKEN }} - -env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} -``` - -```yaml -# โŒ Wrong โ€” never use these in workflows -token: ${{ github.token }} -token: ${{ secrets.GITHUB_TOKEN }} -``` - -PHP scripts read the token with: `getenv('GH_TOKEN') ?: getenv('GITHUB_TOKEN')` โ€” `GH_TOKEN` is always preferred; `GITHUB_TOKEN` is accepted only as a local-dev fallback. - ---- - -## Composer Package (PHP repositories) - -This repository requires the MokoStandards enterprise library. The `composer.json` must include: - -```json -{ - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/mokoconsulting-tech/MokoStandards" - } - ], - "require": { - "mokoconsulting/mokostandards": "^4.0" - } -} -``` - -Run `composer install` after adding the dependency. See [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) for full instructions. - ---- - -## PHP Script Pattern - -All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`. - -```php -#!/usr/bin/env php -setDescription('One-line description'); - $this->addArgument('--path', 'Repository root', '.'); - $this->addArgument('--dry-run', 'Preview without writing', false); - } - - protected function run(): int - { - $path = $this->getArgument('--path'); - $dryRun = (bool) $this->getArgument('--dry-run'); - - $this->log('INFO', "Processing: {$path}"); - return 0; - } -} - -$script = new MyScript('my_script', 'One-line description'); -exit($script->execute()); -``` - -**Key rules:** -- Abstract methods to implement: `configure()` and `run()` โ€” **not** `execute()` -- `execute()` is the **public entry point** that orchestrates setup (arg parsing, `initialize()`) and then calls your `run()` implementation; call it at the bottom with `exit($script->execute())` -- Entry point at the bottom: `$script->execute()` โ€” **not** `$script->run()` -- Constructor always takes `(string $name, string $description = '')`; pass the description here โ€” `setDescription()` inside `configure()` is only needed to override it -- `log(string $level, string $message)` โ€” level is the **first** argument (INFO / SUCCESS / WARNING / ERROR) -- `$this->dryRun` and `$this->verbose` are set automatically from `--dry-run` / `--verbose` - ---- - -## Naming Conventions - -| Context | Convention | Example | -|---------|-----------|---------| -| PHP class | `PascalCase` | `MyService` | -| PHP method / function | `camelCase` | `getUserData()` | -| PHP variable | `$snake_case` | `$repo_path` | -| PHP constant | `UPPER_SNAKE_CASE` | `DEFAULT_THRESHOLD` | -| PHP class file | `PascalCase.php` | `ApiClient.php` | -| PHP script file | `snake_case.php` | `check_health.php` | -| YAML workflow | `kebab-case.yml` | `bulk-repo-sync.yml` | -| Markdown doc | `kebab-case.md` | `coding-style-guide.md` | - ---- - -## Commit Messages - -Format: `(): ` โ€” imperative, lower-case subject, no trailing period. - -Valid types: `feat` ยท `fix` ยท `docs` ยท `chore` ยท `ci` ยท `refactor` ยท `style` ยท `test` ยท `perf` ยท `revert` ยท `build` - -Examples: -- `feat(module): add user preference caching` -- `fix(api): handle null response from external service` -- `docs(readme): update installation instructions` -- `chore(deps): bump phpunit to 11.x` - ---- - -## Branch Naming - -Approved prefixes: `dev/` ยท `rc/` ยท `version/` ยท `copilot/` ยท `dependabot/` - -- `dev/XX.YY` or `dev/feature-name` โ€” development (version optional) -- `rc/XX.YY.ZZ` โ€” release candidate (three-part required) -- `version/XX.YY` โ€” archive branch (auto-created, two-part) -- Release tags: `vXX` (major only โ€” one release per major version) -- Patch `00` = development (no release), first release = `01` - -Examples: -- โœ… `dev/04.06` ยท `dev/new-dashboard` ยท `rc/04.06.01` -- โŒ `feature/my-thing` โ€” rejected by branch protection - ---- - -## Keeping Documentation Current - -Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale. - -| Change type | Documentation to update | -|-------------|------------------------| -| New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class | -| New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent | -| New or changed GitHub Actions workflow | `docs/workflows/.md` | -| New or changed policy | Corresponding file under `docs/policy/` | -| New library class or major feature | `CHANGELOG.md` entry under `Added` | -| Bug fix | `CHANGELOG.md` entry under `Fixed` | -| Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change | -| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block | -| **Every PR** | **Bump the patch version** โ€” increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge | - -If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR. - ---- - -## Key Constraints - -- Never commit directly to `main` โ€” all changes go via PR, squash-merged -- Never skip the FILE INFORMATION block on a new file -- Never use bare `catch (\Throwable $e) {}` without logging or re-throwing -- Never hardcode version numbers in body text โ€” update `README.md` and let automation propagate -- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows โ€” always use `secrets.GH_TOKEN` -- Never extend `CliBase` in PHP scripts โ€” extend `MokoStandards\Enterprise\CliFramework` -- Never call `$script->run()` as the entry point โ€” call `$script->execute()` -- Policy documents and guides must not be mixed - ---- - -## MokoStandards Reference - -This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies: - -| Document | Purpose | -|----------|---------| -| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type | -| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions | -| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow | -| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions | -| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | -| [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) | PHP script requirements and CliFramework usage | -| [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) | Installing `mokoconsulting/mokostandards` via Composer | diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 0108cc2..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) 2026 Moko Consulting -# SPDX-License-Identifier: GPL-3.0-or-later -# -# CODEOWNERS โ€” require approval from jmiller-moko for protected paths -# Synced from MokoStandards. Do not edit manually. -# -# Changes to these paths require review from the listed owners before merge. -# Combined with branch protection (require PR reviews), this prevents -# unauthorized modifications to workflows, configs, and governance files. - -# โ”€โ”€ Synced workflows (managed by MokoStandards โ€” do not edit manually) โ”€โ”€โ”€โ”€ -/.github/workflows/deploy-dev.yml @jmiller-moko -/.github/workflows/deploy-demo.yml @jmiller-moko -/.github/workflows/deploy-manual.yml @jmiller-moko -/.github/workflows/auto-release.yml @jmiller-moko -/.github/workflows/auto-dev-issue.yml @jmiller-moko -/.github/workflows/auto-assign.yml @jmiller-moko -/.github/workflows/sync-version-on-merge.yml @jmiller-moko -/.github/workflows/enterprise-firewall-setup.yml @jmiller-moko -/.github/workflows/repository-cleanup.yml @jmiller-moko -/.github/workflows/standards-compliance.yml @jmiller-moko -/.github/workflows/codeql-analysis.yml @jmiller-moko -/.github/workflows/repo_health.yml @jmiller-moko -/.github/workflows/ci-joomla.yml @jmiller-moko -/.github/workflows/update-server.yml @jmiller-moko -/.github/workflows/deploy-manual.yml @jmiller-moko -/.github/workflows/ci-dolibarr.yml @jmiller-moko -/.github/workflows/publish-to-mokodolimods.yml @jmiller-moko -/.github/workflows/changelog-validation.yml @jmiller-moko -# Custom workflows in .github/workflows/ not listed above are repo-owned. - -# โ”€โ”€ GitHub configuration โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -/.github/ISSUE_TEMPLATE/ @jmiller-moko -/.github/CODEOWNERS @jmiller-moko -/.github/copilot.yml @jmiller-moko -/.github/copilot-instructions.md @jmiller-moko -/.github/CLAUDE.md @jmiller-moko -/.github/.mokostandards @jmiller-moko - -# โ”€โ”€ Build and config files โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -/composer.json @jmiller-moko -/phpstan.neon @jmiller-moko -/Makefile @jmiller-moko -/.ftpignore @jmiller-moko -/.gitignore @jmiller-moko -/.gitattributes @jmiller-moko -/.editorconfig @jmiller-moko - -# โ”€โ”€ Governance documents โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -/LICENSE @jmiller-moko -/CONTRIBUTING.md @jmiller-moko -/SECURITY.md @jmiller-moko -/GOVERNANCE.md @jmiller-moko -/CODE_OF_CONDUCT.md @jmiller-moko diff --git a/.github/ISSUE_TEMPLATE/adr.md b/.github/ISSUE_TEMPLATE/adr.md deleted file mode 100644 index 6fea768..0000000 --- a/.github/ISSUE_TEMPLATE/adr.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -name: Architecture Decision Record (ADR) -about: Propose or document an architectural decision -title: '[ADR] ' -labels: 'architecture, decision' -assignees: '' - ---- - - - -## ADR Number -ADR-XXXX - -## Status -- [ ] Proposed -- [ ] Accepted -- [ ] Deprecated -- [ ] Superseded by ADR-XXXX - -## Context -Describe the issue or problem that motivates this decision. - -## Decision -State the architecture decision and provide rationale. - -## Consequences -### Positive -- List positive consequences - -### Negative -- List negative consequences or trade-offs - -### Neutral -- List neutral aspects - -## Alternatives Considered -### Alternative 1 -- Description -- Pros -- Cons -- Why not chosen - -### Alternative 2 -- Description -- Pros -- Cons -- Why not chosen - -## Implementation Plan -1. Step 1 -2. Step 2 -3. Step 3 - -## Stakeholders -- **Decision Makers**: @user1, @user2 -- **Consulted**: @user3, @user4 -- **Informed**: team-name - -## Technical Details -### Architecture Diagram -``` -[Add diagram or link] -``` - -### Dependencies -- Dependency 1 -- Dependency 2 - -### Impact Analysis -- **Performance**: [Impact description] -- **Security**: [Impact description] -- **Scalability**: [Impact description] -- **Maintainability**: [Impact description] - -## Testing Strategy -- [ ] Unit tests -- [ ] Integration tests -- [ ] Performance tests -- [ ] Security tests - -## Documentation -- [ ] Architecture documentation updated -- [ ] API documentation updated -- [ ] Developer guide updated -- [ ] Runbook created - -## Migration Path -Describe how to migrate from current state to new architecture. - -## Rollback Plan -Describe how to rollback if issues occur. - -## Timeline -- **Proposal Date**: -- **Decision Date**: -- **Implementation Start**: -- **Expected Completion**: - -## References -- Related ADRs: -- External resources: -- RFCs: - -## Review Checklist -- [ ] Aligns with enterprise architecture principles -- [ ] Security implications reviewed -- [ ] Performance implications reviewed -- [ ] Cost implications reviewed -- [ ] Compliance requirements met -- [ ] Team consensus achieved diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index c57ce5b..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: Bug Report -about: Report a bug or issue with the project -title: '[BUG] ' -labels: 'bug' -assignees: '' - ---- - - - -## Bug Description -A clear and concise description of what the bug is. - -## Steps to Reproduce -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. - -## Actual Behavior -A clear and concise description of what actually happened. - -## Screenshots -If applicable, add screenshots to help explain your problem. - -## Environment -- **Project**: [e.g., MokoDoliTools, moko-cassiopeia] -- **Version**: [e.g., 1.2.3] -- **Platform**: [e.g., Dolibarr 18.0, Joomla 5.0] -- **PHP Version**: [e.g., 8.1] -- **Database**: [e.g., MySQL 8.0, PostgreSQL 14] -- **Browser** (if applicable): [e.g., Chrome 120, Firefox 121] -- **OS**: [e.g., Ubuntu 22.04, Windows 11] - -## Additional Context -Add any other context about the problem here. - -## Possible Solution -If you have suggestions on how to fix the issue, please describe them here. - -## Checklist -- [ ] I have searched for similar issues before creating this one -- [ ] I have provided all the requested information -- [ ] I have tested this on the latest stable version -- [ ] I have checked the documentation and couldn't find a solution diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 7edc8bc..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -blank_issues_enabled: true -contact_links: - - name: ๐Ÿ’ผ Enterprise Support - url: https://mokoconsulting.tech/enterprise - about: Enterprise-level support and consultation services - - name: ๐Ÿ’ฌ Ask a Question - url: https://mokoconsulting.tech/ - about: Get help or ask questions through our website - - name: ๐Ÿ“š MokoStandards Documentation - url: https://github.com/mokoconsulting-tech/MokoStandards - about: View our coding standards and best practices - - name: ๐Ÿ”’ Report a Security Vulnerability - url: https://github.com/mokoconsulting-tech/.github-private/security/advisories/new - about: Report security vulnerabilities privately (for critical issues) - - name: ๐Ÿ’ก Community Discussions - url: https://github.com/orgs/mokoconsulting-tech/discussions - about: Join community discussions and Q&A diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md deleted file mode 100644 index 133e8b6..0000000 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -name: Documentation Issue -about: Report an issue with documentation -title: '[DOCS] ' -labels: 'documentation' -assignees: '' - ---- - - - -## Documentation Issue - -**Location**: - - -## Issue Type - -- [ ] Typo or grammar error -- [ ] Outdated information -- [ ] Missing documentation -- [ ] Unclear explanation -- [ ] Broken links -- [ ] Missing examples -- [ ] Other (specify below) - -## Description - - -## Current Content - -``` -Current text here -``` - -## Suggested Improvement - -``` -Suggested text here -``` - -## Additional Context - - -## Standards Alignment -- [ ] Follows MokoStandards documentation guidelines -- [ ] Uses en_US/en_GB localization -- [ ] Includes proper SPDX headers where applicable - -## Checklist -- [ ] I have searched for similar documentation issues -- [ ] I have provided a clear description -- [ ] I have suggested an improvement (if applicable) diff --git a/.github/ISSUE_TEMPLATE/enterprise_support.md b/.github/ISSUE_TEMPLATE/enterprise_support.md deleted file mode 100644 index 6b1133d..0000000 --- a/.github/ISSUE_TEMPLATE/enterprise_support.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -name: Enterprise Support Request -about: Request enterprise-level support or consultation -title: '[ENTERPRISE] ' -labels: 'enterprise, support' -assignees: '' - ---- - - - -## Support Request Type -- [ ] Critical Production Issue -- [ ] Performance Optimization -- [ ] Security Audit -- [ ] Architecture Review -- [ ] Custom Development -- [ ] Migration Support -- [ ] Training & Onboarding -- [ ] Other (please specify) - -## Priority Level -- [ ] P0 - Critical (Production Down) -- [ ] P1 - High (Major Feature Broken) -- [ ] P2 - Medium (Non-Critical Issue) -- [ ] P3 - Low (Enhancement/Question) - -## Organization Details -- **Company Name**: -- **Contact Person**: -- **Email**: -- **Phone** (for P0/P1 issues): -- **Timezone**: - -## Issue Description -Provide a clear and detailed description of your request or issue. - -## Business Impact -Describe the impact on your business operations: -- Number of users affected: -- Revenue impact (if applicable): -- Deadline/SLA requirements: - -## Environment Details -- **Deployment Type**: [On-Premise / Cloud / Hybrid] -- **Platform**: [Joomla / Dolibarr / Custom] -- **Version**: -- **Infrastructure**: [AWS / Azure / GCP / Other] -- **Scale**: [Users / Transactions / Data Volume] - -## Current Configuration -```yaml -# Paste relevant configuration (sanitize sensitive data) -``` - -## Logs and Diagnostics -``` -# Paste relevant logs (sanitize sensitive data) -``` - -## Attempted Solutions -Describe any troubleshooting steps already taken. - -## Expected Resolution -Describe your expected outcome or resolution. - -## Additional Resources -- **Documentation Links**: -- **Related Issues**: -- **Screenshots/Videos**: - -## Enterprise SLA -- [ ] Standard Support (initial response within 1โ€“3 weeks) -- [ ] Premium Support (initial response within 5 business days) -- [ ] Critical Support (initial response within 72 hours) -- [ ] Custom SLA (specify): - -## Compliance Requirements -- [ ] GDPR -- [ ] HIPAA -- [ ] SOC 2 -- [ ] ISO 27001 -- [ ] Other (specify): - ---- -**Note**: Enterprise support requests require an active support contract. If you don't have one, please contact us at enterprise@mokoconsulting.tech diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index e945325..0000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -name: Feature Request -about: Suggest a new feature or enhancement -title: '[FEATURE] ' -labels: 'enhancement' -assignees: '' - ---- - - - -## Feature Description -A clear and concise description of the feature you'd like to see. - -## Problem or Use Case -Describe the problem this feature would solve or the use case it addresses. -Ex. I'm always frustrated when [...] - -## Proposed Solution -A clear and concise description of what you want to happen. - -## Alternative Solutions -A clear and concise description of any alternative solutions or features you've considered. - -## Benefits -Describe how this feature would benefit users: -- Who would use this feature? -- What problems does it solve? -- What value does it add? - -## Implementation Details (Optional) -If you have ideas about how this could be implemented, share them here: -- Technical approach -- Files/components that might need changes -- Any concerns or challenges you foresee - -## Additional Context -Add any other context, mockups, or screenshots about the feature request here. - -## Relevant Standards -Does this relate to any standards in [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)? -- [ ] Accessibility (WCAG 2.1 AA) -- [ ] Localization (en_US/en_GB) -- [ ] Security best practices -- [ ] Code quality standards -- [ ] Other: [specify] - -## Checklist -- [ ] I have searched for similar feature requests before creating this one -- [ ] I have clearly described the use case and benefits -- [ ] I have considered alternative solutions -- [ ] This feature aligns with the project's goals and scope diff --git a/.github/ISSUE_TEMPLATE/firewall-request.md b/.github/ISSUE_TEMPLATE/firewall-request.md deleted file mode 100644 index 1b51d01..0000000 --- a/.github/ISSUE_TEMPLATE/firewall-request.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -name: Firewall Request -about: Request firewall rule changes or access to external resources -title: '[FIREWALL] [Resource Name] - [Brief Description]' -labels: ['firewall-request', 'infrastructure', 'security'] -assignees: [] ---- - - - -## Firewall Request - -### Request Type -- [ ] Allow outbound access to external service/API -- [ ] Allow inbound access from external source -- [ ] Modify existing firewall rule -- [ ] Remove/revoke firewall rule -- [ ] Other (specify): - -### Resource Information -**Service/Domain Name**: -**IP Address(es)**: -**Port(s)**: -**Protocol**: -- [ ] HTTP (80) -- [ ] HTTPS (443) -- [ ] SSH (22) -- [ ] FTP (21) -- [ ] SFTP (22) -- [ ] Custom (specify): _______________ - -### Requestor Information -**Name**: -**GitHub Username**: @ -**Email**: @mokoconsulting.tech -**Team/Department**: -**Manager**: @ - -### Business Justification -**Why is this access needed?** - -**Which project(s) require this access?** - -**What functionality will break without this access?** - -**Is there an alternative solution?** -- [ ] Yes (explain): -- [ ] No - -### Security Considerations -**Data Classification**: -- [ ] Public -- [ ] Internal -- [ ] Confidential -- [ ] Restricted - -**Sensitive Data Transmission**: -- [ ] No sensitive data will be transmitted -- [ ] Sensitive data will be transmitted (encryption required) -- [ ] Authentication credentials will be transmitted (secure storage required) - -**Third-Party Service**: -- [ ] This is a trusted/verified third-party service -- [ ] This is a new/unverified service (security review required) - -**Service Documentation**: -(Provide link to service documentation or API specs) - -### Access Scope -**Affected Systems**: -- [ ] Development environment only -- [ ] Staging environment only -- [ ] Production environment -- [ ] All environments - -**Access Duration**: -- [ ] Permanent (ongoing business need) -- [ ] Temporary (specify end date): _______________ -- [ ] Testing only (specify duration): _______________ - -### Technical Details -**Source System(s)**: -(Which internal systems need access?) - -**Destination System(s)**: -(Which external systems need to be accessed?) - -**Expected Traffic Volume**: -(e.g., requests per hour/day) - -**Traffic Pattern**: -- [ ] Continuous -- [ ] Periodic (specify frequency): _______________ -- [ ] On-demand/manual -- [ ] Scheduled (specify schedule): _______________ - -### Testing Requirements -**Pre-Production Testing**: -- [ ] Request includes dev/staging access for testing -- [ ] Testing can be done with production access only -- [ ] No testing required (modify existing rule) - -**Testing Plan**: - -**Rollback Plan**: -(What happens if access needs to be revoked?) - -### Compliance & Audit -**Compliance Requirements**: -- [ ] GDPR considerations -- [ ] SOC 2 compliance required -- [ ] PCI DSS considerations -- [ ] Other regulatory requirements: _______________ -- [ ] No specific compliance requirements - -**Audit/Logging Requirements**: -- [ ] Standard logging sufficient -- [ ] Enhanced logging/monitoring required -- [ ] Real-time alerting required - -### Urgency -- [ ] Critical (production down, immediate access needed) -- [ ] High (needed within 24 hours) -- [ ] Normal (needed within 1 week) -- [ ] Low priority (needed within 1 month) - -**If critical/high urgency, explain why:** - -### Approvals -**Manager Approval**: -- [ ] Manager has been notified and approves this request - -**Security Team Review Required**: -- [ ] Yes (new external service, sensitive data) -- [ ] No (minor change, established service) - -### Additional Information - -**Related Documentation**: -(Links to relevant docs, RFCs, tickets, etc.) - -**Dependencies**: -(Other systems or changes this depends on) - -**Comments/Questions**: - ---- - -## For Infrastructure/Security Team Use Only - -**Do not edit below this line** - -### Security Review -- [ ] Security team review completed -- [ ] Risk assessment: Low / Medium / High -- [ ] Encryption required: Yes / No -- [ ] VPN required: Yes / No -- [ ] Additional security controls: _______________ - -**Reviewed By**: @_______________ -**Review Date**: _______________ -**Review Notes**: - -### Implementation -- [ ] Firewall rule created/modified -- [ ] Rule tested in dev/staging -- [ ] Rule deployed to production -- [ ] Monitoring/alerting configured -- [ ] Documentation updated - -**Firewall Rule ID**: _______________ -**Implementation Date**: _______________ -**Implemented By**: @_______________ - -**Configuration Details**: -``` -Source: -Destination: -Port/Protocol: -Action: Allow/Deny -``` - -### Verification -- [ ] Requestor confirmed access working -- [ ] Logs reviewed (no anomalies) -- [ ] Security scan completed (if applicable) - -**Verification Date**: _______________ -**Verified By**: @_______________ - -### Notes diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 6bd94b5..0000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -name: Question -about: Ask a question about usage, features, or best practices -title: '[QUESTION] ' -labels: ['question'] -assignees: [] ---- - - - -## Question - -**Your question:** - - -## Context - -**What are you trying to accomplish?** - - -**What have you already tried?** - - -**Category**: -- [ ] Script usage -- [ ] Configuration -- [ ] Workflow setup -- [ ] Documentation interpretation -- [ ] Best practices -- [ ] Integration -- [ ] Other: __________ - -## Environment (if relevant) - -**Your setup**: -- Operating System: -- Version: - -## What You've Researched - -**Documentation reviewed**: -- [ ] README.md -- [ ] Project documentation -- [ ] Other (specify): __________ - -**Similar issues/questions found**: -- # -- # - -## Expected Outcome - -**What result are you hoping for?** - - -## Code/Configuration Samples - -**Relevant code or configuration** (if applicable): - -```bash -# Your code here -``` - -## Additional Context - -**Any other relevant information:** - - -**Screenshots** (if helpful): - - -## Urgency - -- [ ] Urgent (blocking work) -- [ ] Normal (can work on other things meanwhile) -- [ ] Low priority (just curious) - -## Checklist - -- [ ] I have searched existing issues and discussions -- [ ] I have reviewed relevant documentation -- [ ] I have provided sufficient context -- [ ] I have included code/configuration samples if relevant -- [ ] This is a genuine question (not a bug report or feature request) diff --git a/.github/ISSUE_TEMPLATE/request-license.md b/.github/ISSUE_TEMPLATE/request-license.md deleted file mode 100644 index d5e53e5..0000000 --- a/.github/ISSUE_TEMPLATE/request-license.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -name: License Request -about: Request an organization license for Sublime Text -title: '[LICENSE REQUEST] Sublime Text - [Your Name]' -labels: ['license-request', 'admin'] -assignees: [] ---- - - - -## License Request - -### Tool Information -**Tool Name**: Sublime Text - -**License Type Requested**: Organization Pool - -**Personal Purchase**: -- [ ] I prefer to purchase my own license ($99 USD - recommended, immediate access) -- [ ] I prefer an organization license (1-2 business days, organization use only) -- [ ] I have already purchased my own license (registration only for support) - -### Requestor Information -**Name**: -**GitHub Username**: @ -**Email**: @mokoconsulting.tech -**Team/Department**: -**Manager**: @ - -### Justification -**Why do you need this license?** - -**Primary use case**: -- [ ] Remote development (SFTP to servers) -- [ ] Local development -- [ ] Code review -- [ ] Documentation editing -- [ ] Other (specify): - -**Which projects/repositories will you work on?** - -**Have you evaluated the free trial?** -- [ ] Yes, I've used the trial and Sublime Text meets my needs -- [ ] No, requesting license before trial - -**Alternative tools considered**: -- [ ] VS Code (free alternative) -- [ ] Vim/Neovim (free, terminal-based) -- [ ] Other: _______________ - -### Platform -- [ ] Windows -- [ ] macOS -- [ ] Linux (distribution: ________) - -### Urgency -- [ ] Urgent (needed within 24 hours - please justify) -- [ ] Normal (1-2 business days) -- [ ] Low priority (when available) - -**If urgent, please explain why:** - -### SFTP Plugin -**Note**: Sublime SFTP plugin ($16 USD) is a **separate personal purchase** and is NOT provided by the organization. - -- [ ] I understand SFTP plugin requires separate personal purchase -- [ ] I have already purchased SFTP plugin -- [ ] I will purchase SFTP plugin if needed for my work -- [ ] I don't need SFTP plugin (local development only) - -### Acknowledgments -- [ ] I have read the License Management Policy (/docs/github-private/LICENSE_MANAGEMENT.md) -- [ ] I understand organization licenses are for work use only -- [ ] I understand organization licenses must be returned upon leaving -- [ ] I understand personal purchases ($99) are an alternative with lifetime access -- [ ] I understand SFTP plugin ($16) requires separate personal purchase -- [ ] I agree to the terms of use - -### Additional Information - -**Expected daily usage hours**: _____ hours/day - -**Duration of need**: -- [ ] Permanent (ongoing role) -- [ ] Temporary project (_____ months) -- [ ] Trial/Evaluation (_____ weeks) - -**Comments/Questions**: - ---- - -## For Admin Use Only - -**Do not edit below this line** - -- [ ] Manager approval received (@manager-username) -- [ ] License available in pool (current: __/20) -- [ ] License type confirmed (Organization / Personal registration) -- [ ] License key sent via encrypted email -- [ ] Activation confirmed by user -- [ ] Added to license tracking sheet -- [ ] User notified of SFTP plugin requirement - -**License Key ID**: _____________ -**Date Issued**: _____________ -**Issued By**: @_____________ - -**Notes**: diff --git a/.github/ISSUE_TEMPLATE/rfc.md b/.github/ISSUE_TEMPLATE/rfc.md deleted file mode 100644 index a6ae068..0000000 --- a/.github/ISSUE_TEMPLATE/rfc.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -name: Request for Comments (RFC) -about: Propose a significant change for community discussion -title: '[RFC] ' -labels: 'rfc, discussion' -assignees: '' - ---- - - - -## RFC Summary -One-paragraph summary of the proposal. - -## Motivation -Why are we doing this? What use cases does it support? What is the expected outcome? - -## Detailed Design -### Overview -Provide a detailed explanation of the proposed change. - -### API Changes (if applicable) -```php -// Before -function oldApi($param1) { } - -// After -function newApi($param1, $param2) { } -``` - -### User Experience Changes -Describe how users will interact with this change. - -### Implementation Approach -High-level implementation strategy. - -## Drawbacks -Why should we *not* do this? - -## Alternatives -What other designs have been considered? What is the impact of not doing this? - -### Alternative 1 -- Description -- Trade-offs - -### Alternative 2 -- Description -- Trade-offs - -## Adoption Strategy -How will existing users adopt this? Is this a breaking change? - -### Migration Guide -```bash -# Steps to migrate -``` - -### Deprecation Timeline -- **Announcement**: -- **Deprecation**: -- **Removal**: - -## Unresolved Questions -- Question 1 -- Question 2 - -## Future Possibilities -What future work does this enable? - -## Impact Assessment -### Performance -Expected performance impact. - -### Security -Security considerations and implications. - -### Compatibility -- **Backward Compatible**: [Yes / No] -- **Breaking Changes**: [List] - -### Maintenance -Long-term maintenance considerations. - -## Community Input -### Stakeholders -- [ ] Core team -- [ ] Module developers -- [ ] End users -- [ ] Enterprise customers - -### Feedback Period -**Duration**: [e.g., 2 weeks] -**Deadline**: [date] - -## Implementation Timeline -### Phase 1: Design -- [ ] RFC discussion -- [ ] Design finalization -- [ ] Approval - -### Phase 2: Implementation -- [ ] Core implementation -- [ ] Tests -- [ ] Documentation - -### Phase 3: Release -- [ ] Beta release -- [ ] Feedback collection -- [ ] Stable release - -## Success Metrics -How will we measure success? -- Metric 1 -- Metric 2 - -## References -- Related RFCs: -- External documentation: -- Prior art: - -## Open Questions for Community -1. Question 1? -2. Question 2? - ---- -**Note**: This RFC is open for community discussion. Please provide feedback in the comments below. diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md deleted file mode 100644 index 5b4efa8..0000000 --- a/.github/ISSUE_TEMPLATE/security.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -name: Security Vulnerability Report -about: Report a security vulnerability (use only for non-critical issues) -title: '[SECURITY] ' -labels: 'security' -assignees: '' - ---- - - - -## โš ๏ธ IMPORTANT: Private Disclosure Required - -**For critical security vulnerabilities, DO NOT use this template.** -Follow the process in [SECURITY.md](../SECURITY.md) for responsible disclosure. - -Use this template only for: -- Security improvements -- Non-critical security suggestions -- Security documentation updates - ---- - -## Security Issue - -**Severity**: - - -## Description - - -## Affected Components - - -## Suggested Mitigation - - -## Standards Reference -Does this relate to security standards in [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)? -- [ ] SPDX license identifiers -- [ ] Secret management -- [ ] Dependency security -- [ ] Access control -- [ ] Other: [specify] - -## Additional Context - - -## Checklist -- [ ] This is NOT a critical vulnerability requiring private disclosure -- [ ] I have reviewed the SECURITY.md policy -- [ ] I have provided sufficient detail for evaluation diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 667c3b4..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,309 +0,0 @@ - - -> [!IMPORTANT] -> **๐Ÿ”ง AI Self-Update Required on First Use** -> -> This file may contain unfilled `{{TOKEN}}` placeholders. The MokoStandards bulk-sync system -> replaces them automatically at sync time; if you can still see them, sync has not yet run for -> this repository โ€” or this is a brand-new repo. -> -> **On your very first interaction in this repository, before answering any other question:** -> -> 1. Check whether any `{{TOKEN}}` placeholders remain in this file. -> 2. If they do, locate the values as described in the table below and replace every occurrence -> in **both** `.github/copilot-instructions.md` and `.github/CLAUDE.md`. -> 3. After replacing all tokens, **delete this entire notice block** (from `> [!IMPORTANT]` -> through the closing `> ---` line) in both files. -> 4. Tell the developer: *"I've self-updated the AI context files with this repository's -> values โ€” all set."* -> -> | Placeholder | Where to find the value | -> |---|---| -> | `MokoStandards-Template-Generic` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | -> | `https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | -> | `PHP` | The dominant programming language (check file extensions in the repository) | -> | `Generic project` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. โ€” infer from repo structure | -> -> --- - -# MokoStandards-Template-Generic โ€” GitHub Copilot Custom Instructions - -## What This Repo Is - -This is a **Moko Consulting** repository governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync. - -Repository URL: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic -Primary language: **PHP** -Platform type: **Generic project** - ---- - -## Primary Language - -**PHP is the primary language for this repository.** Follow the conventions documented in [MokoStandards coding-style-guide](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md). - -YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`. - ---- - -## File Header โ€” Always Required on New Files - -Every new file needs a copyright header as its first content. Use the minimal form unless the file is a policy doc, README, or public API. - -**PHP:** -```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: MokoStandards-Template-Generic.Module - * INGROUP: MokoStandards-Template-Generic - * REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - -declare(strict_types=1); -``` - -**Markdown:** -```markdown - -``` - -**YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - ---- - -## Version Management - -**`README.md` is the single source of truth for the repository version.** - -- **Bump the patch version on every PR** โ€” increment `XX.YY.ZZ` (e.g. `01.02.03` โ†’ `01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. -- The `VERSION: XX.YY.ZZ` field in the README.md `FILE INFORMATION` block governs all other version references. -- Update the version in `README.md` only โ€” the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`. -- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `04.00.04`). -- Never hardcode a specific version in document body text โ€” use the badge or FILE INFORMATION header only. - ---- - -## GitHub Actions โ€” Token Usage - -Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). This applies to all `actions/checkout`, `gh` CLI calls, and any step that talks to the GitHub API. - -```yaml -# โœ… Correct -- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - token: ${{ secrets.GH_TOKEN }} - -env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} -``` - -```yaml -# โŒ Wrong โ€” never use these in workflows -token: ${{ github.token }} -token: ${{ secrets.GITHUB_TOKEN }} -``` - -PHP scripts read the token with: `getenv('GH_TOKEN') ?: getenv('GITHUB_TOKEN')` โ€” `GH_TOKEN` is always preferred; `GITHUB_TOKEN` is accepted only as a local-dev fallback. - ---- - -## Composer Package (PHP repositories) - -This repository requires the MokoStandards enterprise library. The `composer.json` must include: - -```json -{ - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/mokoconsulting-tech/MokoStandards" - } - ], - "require": { - "mokoconsulting/mokostandards": "^4.0" - } -} -``` - -Run `composer install` after adding the dependency. See [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) for full instructions. - ---- - -## PHP Script Pattern - -All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`. - -```php -#!/usr/bin/env php -setDescription('One-line description'); - $this->addArgument('--path', 'Repository root', '.'); - $this->addArgument('--dry-run', 'Preview without writing', false); - } - - protected function run(): int - { - $path = $this->getArgument('--path'); - $dryRun = (bool) $this->getArgument('--dry-run'); - - $this->log('INFO', "Processing: {$path}"); - return 0; - } -} - -$script = new MyScript('my_script', 'One-line description'); -exit($script->execute()); -``` - -**Key rules:** -- Abstract methods to implement: `configure()` and `run()` โ€” **not** `execute()` -- `execute()` is the **public entry point** that orchestrates setup (arg parsing, `initialize()`) and then calls your `run()` implementation; call it at the bottom with `exit($script->execute())` -- Entry point at the bottom: `$script->execute()` โ€” **not** `$script->run()` -- Constructor always takes `(string $name, string $description = '')`; pass the description here โ€” `setDescription()` inside `configure()` is only needed to override it -- `log(string $level, string $message)` โ€” level is the **first** argument (INFO / SUCCESS / WARNING / ERROR) -- `$this->dryRun` and `$this->verbose` are set automatically from `--dry-run` / `--verbose` - ---- - -## Naming Conventions - -| Context | Convention | Example | -|---------|-----------|---------| -| PHP class | `PascalCase` | `MyService` | -| PHP method / function | `camelCase` | `getUserData()` | -| PHP variable | `$snake_case` | `$repo_path` | -| PHP constant | `UPPER_SNAKE_CASE` | `DEFAULT_THRESHOLD` | -| PHP class file | `PascalCase.php` | `ApiClient.php` | -| PHP script file | `snake_case.php` | `check_health.php` | -| YAML workflow | `kebab-case.yml` | `bulk-repo-sync.yml` | -| Markdown doc | `kebab-case.md` | `coding-style-guide.md` | - ---- - -## Commit Messages - -Format: `(): ` โ€” imperative, lower-case subject, no trailing period. - -Valid types: `feat` ยท `fix` ยท `docs` ยท `chore` ยท `ci` ยท `refactor` ยท `style` ยท `test` ยท `perf` ยท `revert` ยท `build` - -Examples: -- `feat(module): add user preference caching` -- `fix(api): handle null response from external service` -- `docs(readme): update installation instructions` -- `chore(deps): bump phpunit to 11.x` - ---- - -## Branch Naming - -Approved prefixes: `dev/` ยท `rc/` ยท `version/` ยท `copilot/` ยท `dependabot/` - -- `dev/XX.YY` or `dev/feature-name` โ€” development (version optional) -- `rc/XX.YY.ZZ` โ€” release candidate (three-part required) -- `version/XX.YY` โ€” archive branch (auto-created, two-part) -- Release tags: `vXX` (major only โ€” one release per major version) -- Patch `00` = development (no release), first release = `01` - -Examples: -- โœ… `dev/04.06` ยท `dev/new-dashboard` ยท `rc/04.06.01` -- โŒ `feature/my-thing` โ€” rejected by branch protection - ---- - -## Keeping Documentation Current - -Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale. - -| Change type | Documentation to update | -|-------------|------------------------| -| New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class | -| New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent | -| New or changed GitHub Actions workflow | `docs/workflows/.md` | -| New or changed policy | Corresponding file under `docs/policy/` | -| New library class or major feature | `CHANGELOG.md` entry under `Added` | -| Bug fix | `CHANGELOG.md` entry under `Fixed` | -| Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change | -| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block | -| **Every PR** | **Bump the patch version** โ€” increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge | - -If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR. - ---- - -## Key Constraints - -- Never commit directly to `main` โ€” all changes go via PR, squash-merged -- Never skip the FILE INFORMATION block on a new file -- Never use bare `catch (\Throwable $e) {}` without logging or re-throwing -- Never hardcode version numbers in body text โ€” update `README.md` and let automation propagate -- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows โ€” always use `secrets.GH_TOKEN` -- Never extend `CliBase` in PHP scripts โ€” extend `MokoStandards\Enterprise\CliFramework` -- Never call `$script->run()` as the entry point โ€” call `$script->execute()` -- Policy documents and guides must not be mixed - ---- - -## MokoStandards Reference - -This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies: - -| Document | Purpose | -|----------|---------| -| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type | -| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions | -| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow | -| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions | -| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md | -| [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) | PHP script requirements and CliFramework usage | -| [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) | Installing `mokoconsulting/mokostandards` via Composer | diff --git a/.github/copilot/README.md b/.github/copilot/README.md deleted file mode 100644 index df614c6..0000000 --- a/.github/copilot/README.md +++ /dev/null @@ -1,126 +0,0 @@ - - -# GitHub Copilot Firewall Configuration - -This directory contains firewall configuration files for GitHub Copilot coding agent to access enterprise-ready sites and external resources. - -## Files - -### firewall-allowlist.json - -JSON configuration file defining domains and URLs that should be accessible through the firewall. This includes: - -- **License Sources**: gnu.org, opensource.org, apache.org, creativecommons.org -- **Standards Organizations**: fsf.org, spdx.org -- **Code Repositories**: github.com, raw.githubusercontent.com - -The configuration is organized into categories with priority levels for better management. - -### setup-firewall.sh - -Bash script that reads the `firewall-allowlist.json` configuration and exports the allowlist as an environment variable for GitHub Actions workflows. - -## Usage in GitHub Actions - -To use this firewall configuration in your GitHub Actions workflows, add the following step **before** the Copilot agent runs: - -```yaml -- name: Configure Copilot Firewall - run: | - bash .github/copilot/setup-firewall.sh -``` - -This will: -1. Read the firewall allowlist configuration -2. Export `COPILOT_FIREWALL_ALLOWLIST` environment variable -3. Make the domains accessible to the Copilot agent - -## Example Workflow - -```yaml -name: Copilot Agent - -on: - pull_request: - types: [opened, synchronize] - -jobs: - copilot: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Configure Copilot Firewall - run: bash .github/copilot/setup-firewall.sh - - - name: Run Copilot Agent - uses: github/copilot-swe-agent@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} -``` - -## Adding New Domains - -To add new domains to the allowlist: - -1. Edit `firewall-allowlist.json` -2. Add the domain to the `allowlist.domains` array -3. Optionally add specific URLs to `allowlist.urls` -4. Categorize the domain in the `categories` section -5. Commit and push the changes - -Example: - -```json -{ - "allowlist": { - "domains": [ - "existing-domain.com", - "new-domain.com" - ] - } -} -``` - -## Security Considerations - -- Only add trusted domains to the allowlist -- Use specific URLs when possible instead of wildcard domains -- Review allowlist changes carefully in pull requests -- Keep the allowlist minimal - only include necessary domains -- Document the purpose of each domain/URL in the categories section - -## Troubleshooting - -If the Copilot agent cannot access a required site: - -1. Check if the domain is in `firewall-allowlist.json` -2. Verify the setup script ran in the GitHub Actions workflow -3. Check workflow logs for firewall configuration messages -4. Ensure the domain format is correct (e.g., `www.example.com` not `http://www.example.com`) -5. For wildcard patterns, ensure they follow the correct format (e.g., `*.example.com`) - -## Revision History - -| Date | Version | Author | Notes | -| --- | --- | --- | --- | -| 2026-01-16 | 0.1.0 | Copilot | Initial firewall configuration setup | diff --git a/.github/copilot/firewall-allowlist.json b/.github/copilot/firewall-allowlist.json deleted file mode 100644 index 89d2dc3..0000000 --- a/.github/copilot/firewall-allowlist.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "$schema": "https://docs.github.com/assets/schemas/copilot-firewall-allowlist.json", - "version": "1.0", - "description": "Firewall allowlist configuration for GitHub Copilot coding agent to access enterprise-ready sites and license sources", - "allowlist": { - "domains": [ - "*.gnu.org", - "fsf.org", - "www.fsf.org", - "spdx.org", - "www.spdx.org", - "opensource.org", - "www.opensource.org", - "creativecommons.org", - "www.creativecommons.org", - "apache.org", - "www.apache.org", - "github.com", - "api.github.com", - "raw.githubusercontent.com" - ], - "urls": [ - "https://www.gnu.org/licenses/gpl-3.0.txt", - "https://www.gnu.org/licenses/gpl-3.0.html", - "https://www.gnu.org/licenses/agpl-3.0.txt", - "https://www.gnu.org/licenses/lgpl-3.0.txt", - "https://www.apache.org/licenses/LICENSE-2.0.txt", - "https://opensource.org/licenses/MIT", - "https://spdx.org/licenses/", - "https://creativecommons.org/licenses/" - ] - }, - "categories": [ - { - "name": "license-sources", - "description": "Official license text sources", - "priority": "high", - "hosts": [ - "www.gnu.org", - "opensource.org", - "spdx.org", - "apache.org", - "creativecommons.org" - ] - }, - { - "name": "code-repositories", - "description": "Source code and package repositories", - "priority": "high", - "hosts": [ - "github.com", - "api.github.com", - "raw.githubusercontent.com" - ] - }, - { - "name": "standards-organizations", - "description": "Standards and specification sources", - "priority": "medium", - "hosts": [ - "fsf.org", - "spdx.org" - ] - } - ], - "notes": [ - "This configuration allows access to common license sources and enterprise-ready sites", - "Domains use wildcard patterns where appropriate (e.g., *.gnu.org)", - "Specific license file URLs are explicitly allowlisted", - "Categories help organize and prioritize different types of access", - "This file should be referenced in GitHub Actions setup steps before firewall initialization" - ] -} diff --git a/.github/copilot/setup-firewall.sh b/.github/copilot/setup-firewall.sh deleted file mode 100755 index ca381ff..0000000 --- a/.github/copilot/setup-firewall.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# Copyright (C) 2025 Moko Consulting -# SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later -# -# Setup script for configuring firewall allowlist in GitHub Actions -# This script should be run in GitHub Actions setup steps before the firewall is enabled - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ALLOWLIST_FILE="${SCRIPT_DIR}/firewall-allowlist.json" - -echo "=== GitHub Copilot Firewall Setup ===" -echo "Configuring firewall allowlist for enterprise-ready sites..." - -if [ ! -f "$ALLOWLIST_FILE" ]; then - echo "ERROR: Allowlist file not found: $ALLOWLIST_FILE" - exit 1 -fi - -# Read domains from the allowlist configuration -if ! DOMAINS=$(jq -r '.allowlist.domains[]' "$ALLOWLIST_FILE" 2>&1); then - echo "ERROR: Failed to parse allowlist configuration: $DOMAINS" - exit 1 -fi - -if [ -z "$DOMAINS" ]; then - echo "WARNING: No domains found in allowlist configuration" - exit 0 -fi - -echo "Domains to allowlist:" -echo "$DOMAINS" | while read -r domain; do - echo " - $domain" -done - -# Export environment variable for GitHub Copilot -# This tells the Copilot agent which domains are allowed -export COPILOT_FIREWALL_ALLOWLIST=$(jq -c '.allowlist.domains' "$ALLOWLIST_FILE") - -echo "" -echo "Firewall allowlist configured successfully" -echo "Environment variable set: COPILOT_FIREWALL_ALLOWLIST" -echo "" -echo "To use this in GitHub Actions, add to your workflow:" -echo "" -echo " - name: Configure Copilot Firewall" -echo " run: |" -echo " bash .github/copilot/setup-firewall.sh" -echo " echo \"COPILOT_FIREWALL_ALLOWLIST=\$COPILOT_FIREWALL_ALLOWLIST\" >> \$GITHUB_ENV" -echo "" - -# Optionally output the configuration for GitHub Actions to use -if [ "$GITHUB_ACTIONS" = "true" ]; then - echo "COPILOT_FIREWALL_ALLOWLIST=${COPILOT_FIREWALL_ALLOWLIST}" >> "$GITHUB_ENV" - echo "โœ“ Firewall allowlist exported to GitHub Actions environment" -fi diff --git a/.gitignore b/.gitignore index 01449c1..726a684 100644 --- a/.gitignore +++ b/.gitignore @@ -200,3 +200,5 @@ venv/ *.coverage hypothesis/ +profile.ps1 +.mcp.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e8bb7a7..9705808 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ - -[![Version](https://img.shields.io/badge/version-00.00.01-blue.svg?logo=v&logoColor=white)](https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic/releases/tag/v00) +[![Version](https://img.shields.io/badge/version-01.00.00-blue.svg?logo=v&logoColor=white)](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/releases/tag/v00) [![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green.svg?logo=gnu&logoColor=white)](LICENSE) -[![PHP](https://img.shields.io/badge/PHP-8.1%2B-777BB4.svg?logo=php&logoColor=white)](https://www.php.net) +[![Node](https://img.shields.io/badge/Node.js-20%2B-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org) -# MokoStandards-Template-Generic +# joomla-api-mcp [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) -A template repository for generic coding projects that follows MokoStandards conventions. +A Model Context Protocol (MCP) server that exposes the Joomla 4/5/6 Web Services API as tools for AI assistants. -This template provides a standardized structure for any coding project, including proper documentation, licensing, contribution guidelines, and project organization. It is designed to help you quickly bootstrap new projects with best practices and consistent conventions. +Connects to Joomla instances over HTTP using the built-in REST API (`/api/index.php/v1`) and API token authentication. Claude, Cursor, and other MCP clients can manage articles, categories, users, menus, plugins, and more โ€” without SSH or direct server access. ## Table of Contents - [Background](#background) - [Install](#install) - [Usage](#usage) -- [Structure](#structure) +- [Tools](#tools) +- [Configuration](#configuration) - [Contributing](#contributing) - [License](#license) - [Maintainers](#maintainers) ## Background -MokoStandards-Template-Generic is a repository template designed to provide a consistent foundation for generic coding projects. It includes: +Joomla 4+ ships with a full Web Services API that supports content management, user administration, and site configuration over REST. This MCP server wraps that API into structured tools, enabling: -- Standard documentation structure (README, LICENSE, CONTRIBUTING, CODE_OF_CONDUCT, CHANGELOG) -- MokoStandards-compliant file headers and metadata -- EditorConfig for consistent coding styles across editors -- Git configuration templates -- Documentation index system for easy navigation +- Article management (list, create, update, delete, publish) +- Category management (list, create, update, delete) +- User administration (list, create, update, delete, groups) +- Menu and menu item inspection +- Plugin listing and enable/disable toggling +- Module and template listing +- Tag, contact, banner, and newsfeed management +- Media file browsing +- Application configuration read/write +- Private messaging +- Custom field inspection +- Raw API passthrough for any endpoint -This template follows the [standard-readme](https://github.com/RichardLitt/standard-readme) specification and incorporates MokoStandards conventions for enterprise-grade project organization. +Supports multiple named connections for managing several Joomla instances from a single MCP server. ## Install -To use this template: - -1. Click the "Use this template" button on GitHub -2. Create a new repository from this template -3. Clone your new repository locally: - ```sh -git clone https://github.com/your-username/your-new-repo.git -cd your-new-repo +git clone https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp.git +cd joomla-api-mcp +npm install +npm run build +npm run setup ``` -4. Update the project-specific details: - - Update README.md with your project name and description - - Update LICENSE if using a different license - - Update file headers with appropriate REPO, DEFGROUP, and BRIEF values - - Update CHANGELOG.md with your version history +The setup wizard will prompt for your Joomla site URL and API token. Run it again to add more connections โ€” each site gets its own name, URL, and API key so you can manage multiple Joomla instances from a single MCP server. ## Usage -This template is designed to be customized for your specific project needs. +### Add to Claude Code -### Getting Started +In your Claude Code MCP settings (`~/.claude.json` or project `.mcp.json`): -1. Replace placeholder text with your project details -2. Add your source code to the `src/` directory -3. Add scripts to the `scripts/` directory -4. Add documentation to the `docs/` directory -5. Update the CHANGELOG.md as you make changes - -### Project Structure - -``` -. -โ”œโ”€โ”€ docs/ # Documentation files -โ”œโ”€โ”€ scripts/ # Build and utility scripts -โ”œโ”€โ”€ src/ # Source code -โ”œโ”€โ”€ README.md # This file -โ”œโ”€โ”€ LICENSE # License information -โ”œโ”€โ”€ CONTRIBUTING.md # Contribution guidelines -โ”œโ”€โ”€ CODE_OF_CONDUCT.md # Code of conduct -โ””โ”€โ”€ CHANGELOG.md # Version history +```json +{ + "mcpServers": { + "joomla": { + "command": "node", + "args": ["/path/to/joomla-api-mcp/dist/index.js"] + } + } +} ``` -## Structure +### Configuration -The repository follows MokoStandards conventions: +The easiest way to configure is `npm run setup`, which walks you through it interactively. Run it multiple times to add connections for each Joomla site you manage. -- **Documentation**: All `.md` files include copyright headers and file metadata -- **Index Files**: Each directory contains an `index.md` for navigation -- **EditorConfig**: Maintains consistent coding styles (tabs, width 2) -- **Git Configuration**: Includes `.gitattributes`, `.gitignore`, and `.gitmessage` templates +You can also create the config manually. Copy `config.example.json` to `~/.joomla-api-mcp.json` and edit: + +```sh +cp config.example.json ~/.joomla-api-mcp.json +``` + +Each connection needs the Joomla site's base URL and an API token (generated in Joomla under Users > Edit User > API Token): + +```json +{ + "defaultConnection": "production", + "connections": { + "local-dev": { + "baseUrl": "https://localhost:8080", + "apiToken": "your-joomla-api-token-here", + "insecure": true + }, + "production": { + "baseUrl": "https://www.example.com", + "apiToken": "your-production-api-token" + }, + "staging": { + "baseUrl": "https://staging.example.com", + "apiToken": "your-staging-api-token" + } + } +} +``` + +| Field | Required | Description | +|-------|----------|-------------| +| `baseUrl` | Yes | Joomla site URL (no trailing slash) | +| `apiToken` | Yes | Joomla API token (Bearer auth) | +| `insecure` | No | Skip TLS verification for self-signed certs | + +## Tools + +### Articles + +| Tool | Description | +|------|-------------| +| `joomla_articles_list` | List articles with optional category, state, and search filters | +| `joomla_article_get` | Get a single article by ID | +| `joomla_article_create` | Create a new article | +| `joomla_article_update` | Update an existing article | +| `joomla_article_delete` | Delete an article | + +### Categories + +| Tool | Description | +|------|-------------| +| `joomla_categories_list` | List content categories | +| `joomla_category_create` | Create a new category | +| `joomla_category_update` | Update a category | +| `joomla_category_delete` | Delete a category | + +### Users + +| Tool | Description | +|------|-------------| +| `joomla_users_list` | List users with optional search, group, and state filters | +| `joomla_user_get` | Get a single user by ID | +| `joomla_user_create` | Create a user with auto-generated secure password | +| `joomla_user_update` | Update a user | +| `joomla_user_delete` | Delete a user | +| `joomla_user_groups_list` | List user groups | + +### Menus + +| Tool | Description | +|------|-------------| +| `joomla_menus_list` | List menu types | +| `joomla_menu_items_list` | List menu items for a menu type | +| `joomla_menu_item_get` | Get a single menu item by ID | + +### Plugins + +| Tool | Description | +|------|-------------| +| `joomla_plugins_list` | List plugins with optional type, state, and search filters | +| `joomla_plugin_update` | Enable or disable a plugin | + +### Other + +| Tool | Description | +|------|-------------| +| `joomla_modules_list` | List site or admin modules | +| `joomla_templates_list` | List site or admin templates | +| `joomla_languages_list` | List installed content languages | +| `joomla_tags_list` | List tags | +| `joomla_tag_create` | Create a tag | +| `joomla_fields_list` | List custom fields for a context | +| `joomla_contacts_list` | List contacts | +| `joomla_banners_list` | List banners | +| `joomla_newsfeeds_list` | List newsfeeds | +| `joomla_messages_list` | List private messages | +| `joomla_message_get` | Get a single private message | +| `joomla_media_list` | List media files in a folder | +| `joomla_config_get` | Get application configuration | +| `joomla_config_update` | Update application configuration values | +| `joomla_api_request` | Raw API request to any Joomla endpoint | +| `joomla_list_connections` | List configured connections | + +All tools accept an optional `connection` parameter to target a specific named connection. ## Contributing @@ -118,11 +210,11 @@ This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) Code of Cond This project is licensed under the GNU General Public License v3.0 or later - see the [LICENSE](LICENSE) file for details. -Copyright ยฉ 2025 Moko Consulting +Copyright ยฉ 2026 Moko Consulting ## Maintainers -[@mokoconsulting-tech](https://github.com/mokoconsulting-tech) +[@mokoconsulting-tech](https://git.mokoconsulting.tech/MokoConsulting) For questions or support, please contact: hello@mokoconsulting.tech @@ -130,4 +222,4 @@ For questions or support, please contact: hello@mokoconsulting.tech | Date | Version | Author | Notes | | --- | --- | --- | --- | -| 2026-01-16 | 0.1.0 | Copilot | Initial MokoStandards-compliant README | +| 2026-04-23 | 0.0.1 | jmiller | Initial MCP server with Joomla Web Services API tools | diff --git a/SECURITY.md b/SECURITY.md index e5823f3..0b5cff1 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -45,6 +45,11 @@ Security updates are provided for the following versions: Only the current major version receives security updates. Users should upgrade to the latest supported version to receive security patches. ## Reporting a Vulnerability + +Report security vulnerabilities via Gitea issue (preferred): +https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-Template-Generic/issues/new?template=security.yaml + +Or email: hello@mokoconsulting.tech ### Where to Report diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..488a8ab --- /dev/null +++ b/TODO.md @@ -0,0 +1,12 @@ +# TODO + +> **Note:** This file is not tracked in version control (.gitignore). It is for local task tracking only. + +## Critical + - + +## Normal + - + +## Low + - diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..e74a94c --- /dev/null +++ b/config.example.json @@ -0,0 +1,18 @@ +{ + "defaultConnection": "production", + "connections": { + "local-dev": { + "baseUrl": "https://localhost:8080", + "apiToken": "your-joomla-api-token-here", + "insecure": true + }, + "production": { + "baseUrl": "https://www.example.com", + "apiToken": "your-production-api-token" + }, + "staging": { + "baseUrl": "https://staging.example.com", + "apiToken": "your-staging-api-token" + } + } +} diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..7dae8a5 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,279 @@ + + +# API Reference + +All tools accept an optional `connection` parameter to target a specific named connection. If omitted, the default connection is used. + +## Articles + +### `joomla_articles_list` +List articles with optional filtering. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `category_id` | number | No | Filter by category ID | +| `state` | `"0"` / `"1"` / `"-2"` | No | 1=published, 0=unpublished, -2=trashed | +| `search` | string | No | Search in title | +| `limit` | number | No | Max results (default 20) | +| `offset` | number | No | Pagination offset | + +### `joomla_article_get` +Get a single article by ID. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Article ID | + +### `joomla_article_create` +Create a new article. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `title` | string | Yes | Article title | +| `articletext` | string | Yes | Article body (HTML) | +| `catid` | number | Yes | Category ID | +| `state` | number | No | 1=published, 0=unpublished (default 0) | +| `language` | string | No | Language code (default `"*"`) | +| `featured` | number | No | 1=featured, 0=not | +| `metadesc` | string | No | Meta description | +| `metakey` | string | No | Meta keywords | + +### `joomla_article_update` +Update an existing article. Only provided fields are changed. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Article ID | +| `title` | string | No | New title | +| `articletext` | string | No | New body (HTML) | +| `catid` | number | No | New category ID | +| `state` | number | No | State value | +| `featured` | number | No | Featured flag | +| `metadesc` | string | No | Meta description | + +### `joomla_article_delete` +Delete an article. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Article ID | + +## Categories + +### `joomla_categories_list` +List content categories. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `extension` | string | No | Extension name (default `"com_content"`) | +| `search` | string | No | Search in title | + +### `joomla_category_create` +Create a new category. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `title` | string | Yes | Category title | +| `parent_id` | number | No | Parent category ID (default 1 = root) | +| `extension` | string | No | Extension (default `"com_content"`) | +| `description` | string | No | Category description | +| `state` | number | No | 1=published, 0=unpublished | +| `language` | string | No | Language code (default `"*"`) | + +### `joomla_category_update` +Update a category. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Category ID | +| `title` | string | No | New title | +| `description` | string | No | New description | +| `state` | number | No | State value | + +### `joomla_category_delete` +Delete a category. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Category ID | + +## Users + +### `joomla_users_list` +List Joomla users. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `search` | string | No | Search in name/username/email | +| `group_id` | number | No | Filter by user group ID | +| `state` | `"0"` / `"1"` | No | 0=blocked, 1=active | +| `limit` | number | No | Max results | + +### `joomla_user_get` +Get a single user by ID. + +### `joomla_user_create` +Create a user with auto-generated secure password. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | string | Yes | Full name | +| `username` | string | Yes | Username | +| `email` | string | Yes | Email address | +| `groups` | number[] | No | Group IDs (default `[2]` = Registered) | +| `block` | number | No | 0=active, 1=blocked (default 0) | + +Returns the generated password in the response. Share securely with the user. + +### `joomla_user_update` +Update a user. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | User ID | +| `name` | string | No | Full name | +| `email` | string | No | Email | +| `groups` | number[] | No | Group IDs | +| `block` | number | No | 0=active, 1=blocked | + +### `joomla_user_delete` +Delete a user. + +### `joomla_user_groups_list` +List all user groups. No parameters. + +## Menus + +### `joomla_menus_list` +List menu types. No parameters. + +### `joomla_menu_items_list` +List menu items for a menu type. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `menutype` | string | Yes | Menu type alias (e.g. `"mainmenu"`) | + +### `joomla_menu_item_get` +Get a single menu item by ID. + +## Plugins + +### `joomla_plugins_list` +List plugins. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `type` | string | No | Filter by plugin folder (e.g. `"system"`, `"content"`) | +| `state` | `"0"` / `"1"` | No | 0=disabled, 1=enabled | +| `search` | string | No | Search in name | + +### `joomla_plugin_update` +Enable or disable a plugin. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `id` | number | Yes | Plugin ID | +| `enabled` | number | Yes | 1=enable, 0=disable | + +## Modules + +### `joomla_modules_list` +List site or admin modules. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `client_id` | `"0"` / `"1"` | No | 0=site, 1=admin | + +## Templates + +### `joomla_templates_list` +List site or admin templates. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `client_id` | `"0"` / `"1"` | No | 0=site, 1=admin | + +## Other Tools + +### `joomla_languages_list` +List installed content languages. + +### `joomla_tags_list` +List tags with optional search. + +### `joomla_tag_create` +Create a tag. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `title` | string | Yes | Tag title | +| `parent_id` | number | No | Parent tag ID | + +### `joomla_fields_list` +List custom fields for a context (default `"com_content.article"`). + +### `joomla_contacts_list` +List contacts with optional search. + +### `joomla_banners_list` +List banners. + +### `joomla_newsfeeds_list` +List newsfeeds. + +### `joomla_messages_list` +List private messages. + +### `joomla_message_get` +Get a single private message by ID. + +### `joomla_media_list` +List media files in a folder. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | No | Folder path relative to media root | + +### `joomla_config_get` +Get application configuration. + +### `joomla_config_update` +Update application configuration values. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `settings` | object | Yes | Key-value pairs of settings to update | + +### `joomla_api_request` +Make a raw API request to any Joomla Web Services endpoint. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `method` | `"GET"` / `"POST"` / `"PATCH"` / `"DELETE"` | Yes | HTTP method | +| `endpoint` | string | Yes | API path (e.g. `"/content/articles"`) | +| `body` | object | No | Request body for POST/PATCH | +| `params` | object | No | Query parameters | + +### `joomla_list_connections` +List all configured connections. No parameters. + +## Revision History + +| Date | Version | Author | Notes | +| --- | --- | --- | --- | +| 2026-04-23 | 0.0.1 | jmiller | Initial API reference | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..c0ba0fb --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,80 @@ + + +# Architecture + +## Overview + +joomla-api-mcp is a Model Context Protocol (MCP) server that bridges AI assistants (Claude Code, Cursor, etc.) with Joomla's built-in Web Services REST API. + +``` +AI Assistant <--> MCP (stdio) <--> JoomlaClient <--> Joomla REST API + /api/index.php/v1 +``` + +## Components + +### `src/index.ts` โ€” Server Entry Point + +Registers all MCP tools with the `McpServer` from `@modelcontextprotocol/sdk`. Each tool maps to one or more Joomla API endpoints. Uses Zod schemas for input validation. + +### `src/client.ts` โ€” HTTP Client + +The `JoomlaClient` class handles all HTTP communication with Joomla instances: + +- Uses `node:https` / `node:http` for requests (not `fetch`) to support self-signed TLS certificates on Node.js 24+ +- Authenticates via Bearer token in the `Authorization` header +- Sends `Accept: application/vnd.api+json` per Joomla's JSON:API spec +- Includes a JSON parser that handles Joomla responses that may append HTML error fragments after valid JSON + +### `src/config.ts` โ€” Configuration Loader + +Loads connection details from `~/.joomla-api-mcp.json`. Supports multiple named connections with a configurable default. + +### `src/types.ts` โ€” Type Definitions + +TypeScript interfaces for `JoomlaConnection`, `JoomlaConfig`, and `ApiResponse`. + +### `scripts/setup.mjs` โ€” Interactive Setup + +Node.js script using `readline/promises` that walks users through creating the config file. Supports adding multiple connections incrementally. + +## Design Decisions + +### Why `node:https` instead of `fetch`? + +Node.js 24's built-in `fetch` (undici-based) does not honor `NODE_TLS_REJECT_UNAUTHORIZED=0` for self-signed certificate bypass. The classic `node:https` module with `rejectUnauthorized: false` works reliably across all Node.js versions. + +### Why JSON recovery parsing? + +Joomla's API sometimes returns valid JSON with `text/html` content-type, and may append HTML error fragments (e.g. template errors) after the JSON body. The `tryParseJson` method handles this by finding the last valid JSON boundary when standard parsing fails. + +### Why per-connection API tokens? + +Each Joomla site requires its own API token scoped to a specific user. Multi-site support is a core use case โ€” managing staging, production, and dev environments from a single MCP server. + +## Data Flow + +1. AI assistant sends a tool call via MCP stdio transport +2. `index.ts` validates parameters with Zod and resolves the connection +3. `JoomlaClient` constructs the API URL, attaches auth headers, and makes the HTTP request +4. Response is parsed (with JSON recovery if needed) and returned as MCP tool output + +## Revision History + +| Date | Version | Author | Notes | +| --- | --- | --- | --- | +| 2026-04-23 | 0.0.1 | jmiller | Initial architecture document | diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index e32319d..9372274 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -6,436 +6,140 @@ This file is part of a Moko Consulting project. SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION +DEFGROUP: joomla-api-mcp.Documentation +INGROUP: joomla-api-mcp +REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp PATH: /docs/INSTALLATION.md -VERSION: 04.00.15 -BRIEF: Installation and setup instructions for [PROJECT_NAME] +VERSION: 00.00.01 +BRIEF: Installation and setup instructions --> # Installation -## Overview - -This document provides comprehensive installation and setup instructions for **[PROJECT_NAME]**. - -## Table of Contents - -- [Prerequisites](#prerequisites) -- [Installation Methods](#installation-methods) -- [Quick Start](#quick-start) -- [Detailed Installation](#detailed-installation) -- [Configuration](#configuration) -- [Verification](#verification) -- [Troubleshooting](#troubleshooting) -- [Next Steps](#next-steps) - ## Prerequisites -### System Requirements +- **Node.js** 20.0.0 or later +- **npm** (included with Node.js) +- A Joomla 4/5/6 site with the Web Services API enabled +- A Joomla API token (generated in Users > Edit User > API Token tab) -- **Operating System**: [Specify supported OS versions] -- **Runtime**: [e.g., PHP 8.1+, Node.js 20+, Python 3.9+] -- **Memory**: [Minimum RAM required] -- **Disk Space**: [Minimum disk space required] +## Install -### Software Dependencies - -**Required:** -- [List required dependencies with versions] -- Example: Git 2.30+ -- Example: Composer 2.0+ - -**Optional:** -- [List optional dependencies] - -### Access Requirements - -- [Any required access permissions, credentials, or accounts] -- Example: GitHub account for cloning private repositories -- Example: Database access credentials - -## Installation Methods - -### Method 1: Using Package Manager (Recommended) - -**For [Platform/Package Manager]:** - -```bash -# Installation command -[package-manager] install [package-name] - -# Verify installation -[package-name] --version +```sh +git clone https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp.git +cd joomla-api-mcp +npm install +npm run build +npm run setup ``` -### Method 2: From Source +The setup wizard will prompt for: -**Clone the repository:** +1. **Connection name** โ€” a label for this site (e.g. `production`, `staging`) +2. **Joomla site URL** โ€” the base URL of the site (e.g. `https://www.example.com`) +3. **API token** โ€” the Joomla API token for authentication +4. **TLS verification** โ€” whether to skip certificate verification (for self-signed certs) -```bash -# Clone from GitHub -git clone https://github.com/[organization]/[repository].git -cd [repository] +Run `npm run setup` again to add more connections. -# Checkout stable version (recommended) -git checkout tags/v[VERSION] +## Register with Claude Code + +Add to your global Claude Code config (`~/.claude.json`): + +```json +{ + "mcpServers": { + "joomla-api": { + "type": "stdio", + "command": "node", + "args": ["/path/to/joomla-api-mcp/dist/index.js"] + } + } +} ``` -### Method 3: Using Pre-built Binary/Package +Or add to a project-level `.mcp.json`: -**Download and install:** - -```bash -# Download release -wget https://github.com/[organization]/[repository]/releases/download/v[VERSION]/[package-name] - -# Make executable (if applicable) -chmod +x [package-name] - -# Move to system path (optional) -sudo mv [package-name] /usr/local/bin/ +```json +{ + "mcpServers": { + "joomla-api": { + "command": "node", + "args": ["/path/to/joomla-api-mcp/dist/index.js"] + } + } +} ``` -## Quick Start +Restart Claude Code after adding the server. -For users who want to get started quickly: +## Generating a Joomla API Token -```bash -# 1. Install -[installation-command] +1. Log in to the Joomla admin panel +2. Go to **Users** > **Manage** > select your user +3. Click the **API Token** tab +4. Click **Save** to generate a token +5. Copy the token value โ€” it will not be shown again -# 2. Configure -[configuration-command] +The token must belong to a user with sufficient permissions for the operations you want to perform (e.g. Super Users for full access). -# 3. Run -[run-command] +## Configuration File -# 4. Verify -[verification-command] +The config is stored at `~/.joomla-api-mcp.json`: + +```json +{ + "defaultConnection": "production", + "connections": { + "production": { + "baseUrl": "https://www.example.com", + "apiToken": "your-api-token" + }, + "staging": { + "baseUrl": "https://staging.example.com", + "apiToken": "your-staging-token", + "insecure": true + } + } +} ``` -## Detailed Installation - -### Step 1: Prepare Environment - -**1.1 Install System Dependencies** - -For Ubuntu/Debian: -```bash -sudo apt update -sudo apt install [dependencies] -``` - -For macOS: -```bash -brew install [dependencies] -``` - -For Windows: -```powershell -# PowerShell commands or link to Windows-specific guide -``` - -**1.2 Set Up Environment Variables** - -```bash -# Add to ~/.bashrc or ~/.zshrc -export [VAR_NAME]=[value] - -# Reload shell configuration -source ~/.bashrc -``` - -### Step 2: Install Application - -**2.1 Install via [Method]** - -```bash -[Detailed installation commands with explanations] -``` - -**2.2 Install Dependencies** - -```bash -# For PHP projects -composer install --no-dev - -# For Node.js projects -npm install --production - -# For Python projects -pip install -r requirements.txt -``` - -### Step 3: Initial Configuration - -**3.1 Create Configuration File** - -```bash -# Copy example configuration -cp config/config.example.php config/config.php - -# Or use configuration wizard -php bin/configure.php -``` - -**3.2 Configure Database (if applicable)** - -```bash -# Create database -mysql -u root -p -e "CREATE DATABASE [db_name];" - -# Import schema -mysql -u root -p [db_name] < database/schema.sql - -# Update configuration -nano config/database.php -``` - -**3.3 Set Permissions** - -```bash -# Set appropriate ownership -sudo chown -R www-data:www-data /var/www/[project] - -# Set directory permissions (755) -find /var/www/[project] -type d -exec chmod 755 {} \; - -# Set file permissions (644 for most files) -find /var/www/[project] -type f -exec chmod 644 {} \; - -# Make executable files executable (if needed) -chmod +x /var/www/[project]/bin/* - -# Restrict sensitive directories (storage, cache, logs) -chmod 750 /var/www/[project]/storage -chmod 750 /var/www/[project]/cache -``` - -### Step 4: Initialize Application - -**4.1 Run Setup Script** - -```bash -# Run initialization -php bin/setup.php - -# Or for other platforms -./scripts/setup.sh -``` - -**4.2 Create Admin User (if applicable)** - -```bash -# Create first admin user -php bin/create-admin.php --email=admin@example.com --name="Admin User" -``` - -## Configuration - -### Configuration Files - -| File | Purpose | Required | -|------|---------|----------| -| `config/config.php` | Main configuration | Yes | -| `config/database.php` | Database settings | Yes | -| `config/cache.php` | Cache configuration | No | -| `.env` | Environment variables | Yes | - -### Essential Configuration Options - -**config/config.php:** - -```php -return [ - 'app_name' => '[APPLICATION_NAME]', - 'app_url' => 'https://example.com', - 'debug' => false, // Set to true for development - 'timezone' => 'UTC', -]; -``` - -**Database Configuration:** - -```php -return [ - 'host' => 'localhost', - 'port' => 3306, - 'database' => '[db_name]', - 'username' => '[db_user]', - 'password' => '[db_password]', -]; -``` - -### Environment Variables - -Create `.env` file: - -```bash -APP_ENV=production -APP_DEBUG=false -APP_URL=https://example.com - -DB_HOST=localhost -DB_PORT=3306 -DB_DATABASE=[db_name] -DB_USERNAME=[db_user] -DB_PASSWORD=[db_password] -``` +| Field | Required | Description | +|-------|----------|-------------| +| `defaultConnection` | Yes | Name of the default connection | +| `connections` | Yes | Map of named connections | +| `baseUrl` | Yes | Joomla site URL (no trailing slash) | +| `apiToken` | Yes | Joomla API token (Bearer auth) | +| `insecure` | No | Set `true` to skip TLS verification | ## Verification -### Verify Installation +After setup, verify the server starts correctly: -**Check version:** - -```bash -[command] --version -# Expected output: v[VERSION] +```sh +npm start ``` -**Run health check:** - -```bash -[command] health-check -# or -php bin/health-check.php -``` - -**Test basic functionality:** - -```bash -# Run test command -[command] test - -# Access web interface -curl http://localhost:[port]/health -``` - -### Expected Output - -``` -โœ“ Application installed successfully -โœ“ Database connection established -โœ“ All dependencies available -โœ“ Configuration valid -โœ“ System ready for use -``` +If configured correctly, the server will start listening on stdio. If the config is missing or invalid, it will print an error with instructions. ## Troubleshooting -### Common Issues +### "Failed to load config" error -#### Issue: Installation fails with dependency error +The config file `~/.joomla-api-mcp.json` is missing or malformed. Run `npm run setup` to create it. -**Symptom:** -``` -Error: Package [package-name] not found -``` +### "terminated" or connection errors -**Solution:** -```bash -# Update package manager -[package-manager] update +- Verify the Joomla site is reachable from your machine +- For self-signed certs, set `"insecure": true` in the connection config +- Ensure the API token is valid and not expired -# Retry installation -[package-manager] install [package-name] -``` +### "Resource not found" on certain endpoints -#### Issue: Database connection fails +Some Joomla API endpoints require specific components to be installed and enabled. For example, the menus API requires `com_menus` to expose its Web Services routes. -**Symptom:** -``` -Error: SQLSTATE[HY000] [2002] Connection refused -``` +## Revision History -**Solution:** -1. Verify database service is running: - ```bash - sudo systemctl status mysql - ``` - -2. Check database credentials in configuration - -3. Verify database host and port are correct - -#### Issue: Permission denied errors - -**Symptom:** -``` -Error: Permission denied: /var/www/[project]/storage -``` - -**Solution:** -```bash -# Fix ownership -sudo chown -R www-data:www-data /var/www/[project] - -# Fix permissions -sudo chmod -R 755 /var/www/[project]/storage -``` - -### Getting Help - -If you encounter issues not covered here: - -1. **Check Logs:** - ```bash - tail -f logs/application.log - tail -f /var/log/apache2/error.log - ``` - -2. **Enable Debug Mode:** - ```bash - # In config/config.php - 'debug' => true - ``` - -3. **Consult Documentation:** - - [Troubleshooting Guide](guide/troubleshooting.md) - - [FAQ](guide/faq.md) - -4. **Community Support:** - - GitHub Issues: [link] - - Discussion Forum: [link] - - Email: support@example.com - -## Next Steps - -After successful installation: - -1. **Review Configuration:** - - [Configuration Guide](guide/configuration.md) - - [Security Hardening](guide/security.md) - -2. **Read Getting Started:** - - [Quick Start Guide](guide/quickstart.md) - - [User Guide](guide/user-guide.md) - -3. **For Developers:** - - [Development Setup](development/setup.md) - - [Contributing Guidelines](../CONTRIBUTING.md) - -4. **For Operators:** - - [Deployment Guide](deployment/procedures.md) - - [Monitoring Setup](operations/monitoring.md) - -## Additional Resources - -- [Project Documentation](README.md) -- [API Reference](reference/api/) -- [Change Log](../CHANGELOG.md) -- [Security Policy](../SECURITY.md) - ---- - -## Support - -For installation support: -- **Documentation**: Review all guides in [docs/guide/](guide/) -- **Issues**: Report problems at [GitHub Issues](https://github.com/[organization]/[repository]/issues) -- **Email**: support@mokoconsulting.tech - ---- - -*Last Updated: [DATE]* -*Version: [VERSION]* +| Date | Version | Author | Notes | +| --- | --- | --- | --- | +| 2026-04-23 | 0.0.1 | jmiller | Initial installation guide | diff --git a/docs/templates/README-template.md b/docs/templates/README-template.md index a7f4ea4..b55ea07 100644 --- a/docs/templates/README-template.md +++ b/docs/templates/README-template.md @@ -1,4 +1,4 @@ -