chore: cascade main → dev (b28f3be) [skip ci]
#1
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
MokoStandards Repository Manifest
|
||||
Auto-generated by MokoStandards bulk sync.
|
||||
Manual edits to <governance> and <last-synced> may be overwritten.
|
||||
See: docs/standards/mokostandards-file-spec.md
|
||||
-->
|
||||
<mokostandards xmlns="https://standards.mokoconsulting.tech/mokostandards/1.0" schema-version="1.0">
|
||||
<identity>
|
||||
<name>joomla-api-mcp</name>
|
||||
<org>MokoConsulting</org>
|
||||
<description>MCP server for Joomla Web Services API operations</description>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
<governance>
|
||||
<platform>waas-component</platform>
|
||||
<standards-version>04.07.00</standards-version>
|
||||
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/MokoStandards</standards-source>
|
||||
<last-synced>2026-05-02T23:06:09+00:00</last-synced>
|
||||
</governance>
|
||||
<build>
|
||||
<language>Markdown</language>
|
||||
<package-type>joomla-extension</package-type>
|
||||
</build>
|
||||
<deploy>
|
||||
<target name="dev">
|
||||
<host>${{ secrets.DEV_HOST }}</host>
|
||||
<path>${{ secrets.DEV_PATH }}</path>
|
||||
<method>sftp</method>
|
||||
<branch>dev/**</branch>
|
||||
<src-dir>src/</src-dir>
|
||||
</target>
|
||||
<target name="demo">
|
||||
<host>${{ secrets.DEMO_HOST }}</host>
|
||||
<path>${{ secrets.DEMO_PATH }}</path>
|
||||
<method>sftp</method>
|
||||
<branch>main</branch>
|
||||
<src-dir>src/</src-dir>
|
||||
</target>
|
||||
</deploy>
|
||||
<scripts>
|
||||
<script name="lint" phase="lint">
|
||||
<command>make lint</command>
|
||||
<description>Lint via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="validate" phase="validate">
|
||||
<command>make validate</command>
|
||||
<description>Validate via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="test" phase="test">
|
||||
<command>make test</command>
|
||||
<description>Test via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="clean" phase="build">
|
||||
<command>make clean</command>
|
||||
<description>Clean via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="build" phase="build">
|
||||
<command>make build</command>
|
||||
<description>Build via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="package" phase="build">
|
||||
<command>make package</command>
|
||||
<description>Package via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
<script name="release" phase="release">
|
||||
<command>make release</command>
|
||||
<description>Release via make</description>
|
||||
<runner>make</runner>
|
||||
</script>
|
||||
</scripts>
|
||||
</mokostandards>
|
||||
@@ -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
|
||||
@@ -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]+$')
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# 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
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
+1
-1
@@ -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:
|
||||
@@ -1,309 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: MokoStandards.Templates.GitHub
|
||||
INGROUP: MokoStandards.Templates
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||
PATH: /templates/github/copilot-instructions.md.template
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Standard GitHub Copilot custom instructions template for Moko Consulting governed repositories
|
||||
NOTE: Synced to .github/copilot-instructions.md in all governed repositories via bulk sync.
|
||||
Tokens replaced at sync time: MokoStandards-Template-Generic, https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic, PHP, Generic project
|
||||
-->
|
||||
|
||||
> [!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/<repo-name>` |
|
||||
> | `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
|
||||
<?php
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: 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
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: MokoStandards-Template-Generic.Documentation
|
||||
INGROUP: MokoStandards-Template-Generic
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
|
||||
PATH: /docs/file.md
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: One-line description
|
||||
-->
|
||||
```
|
||||
|
||||
**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
|
||||
<?php
|
||||
/* … file header … */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use MokoStandards\Enterprise\CliFramework;
|
||||
|
||||
class MyScript extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->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: `<type>(<scope>): <subject>` — 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/<workflow-name>.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 |
|
||||
@@ -1,54 +0,0 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# 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
|
||||
@@ -1,125 +0,0 @@
|
||||
---
|
||||
name: Architecture Decision Record (ADR)
|
||||
about: Propose or document an architectural decision
|
||||
title: '[ADR] '
|
||||
labels: 'architecture, decision'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/adr.md
|
||||
Description: Issue template for Architecture Decision Records
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## 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
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Report a bug or issue with the project
|
||||
title: '[BUG] '
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/bug_report.md
|
||||
Description: Issue template for bug reports
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## 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
|
||||
@@ -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
|
||||
@@ -1,67 +0,0 @@
|
||||
---
|
||||
name: Documentation Issue
|
||||
about: Report an issue with documentation
|
||||
title: '[DOCS] '
|
||||
labels: 'documentation'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/documentation.md
|
||||
Description: Issue template for documentation-related issues
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## Documentation Issue
|
||||
|
||||
**Location**:
|
||||
<!-- Specify the file, page, or section with the issue -->
|
||||
|
||||
## Issue Type
|
||||
<!-- Mark the relevant option with an "x" -->
|
||||
- [ ] Typo or grammar error
|
||||
- [ ] Outdated information
|
||||
- [ ] Missing documentation
|
||||
- [ ] Unclear explanation
|
||||
- [ ] Broken links
|
||||
- [ ] Missing examples
|
||||
- [ ] Other (specify below)
|
||||
|
||||
## Description
|
||||
<!-- Clearly describe the documentation issue -->
|
||||
|
||||
## Current Content
|
||||
<!-- Quote or describe the current documentation (if applicable) -->
|
||||
```
|
||||
Current text here
|
||||
```
|
||||
|
||||
## Suggested Improvement
|
||||
<!-- Provide your suggestion for how to improve the documentation -->
|
||||
```
|
||||
Suggested text here
|
||||
```
|
||||
|
||||
## Additional Context
|
||||
<!-- Add any other context, screenshots, or references -->
|
||||
|
||||
## 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)
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
name: Enterprise Support Request
|
||||
about: Request enterprise-level support or consultation
|
||||
title: '[ENTERPRISE] '
|
||||
labels: 'enterprise, support'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/enterprise_support.md
|
||||
Description: Issue template for enterprise support requests
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## 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
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest a new feature or enhancement
|
||||
title: '[FEATURE] '
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/feature_request.md
|
||||
Description: Issue template for feature requests
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## 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
|
||||
@@ -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: []
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/firewall-request.md
|
||||
Description: Issue template for firewall rule change and access requests
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-03-11: Added SPDX header and version to match MokoStandards 03.02.00
|
||||
-->
|
||||
|
||||
## 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
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about usage, features, or best practices
|
||||
title: '[QUESTION] '
|
||||
labels: ['question']
|
||||
assignees: []
|
||||
---
|
||||
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
|
||||
## 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)
|
||||
@@ -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: []
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/request-license.md
|
||||
Description: Issue template for organization software license requests
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-03-11: Added SPDX header and version to match MokoStandards 03.02.00
|
||||
-->
|
||||
|
||||
## 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**:
|
||||
@@ -1,141 +0,0 @@
|
||||
---
|
||||
name: Request for Comments (RFC)
|
||||
about: Propose a significant change for community discussion
|
||||
title: '[RFC] '
|
||||
labels: 'rfc, discussion'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/rfc.md
|
||||
Description: Issue template for Request for Comments proposals
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## 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.
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
name: Security Vulnerability Report
|
||||
about: Report a security vulnerability (use only for non-critical issues)
|
||||
title: '[SECURITY] '
|
||||
labels: 'security'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (C) 2024-2026 Moko Consulting Tech
|
||||
|
||||
File: .github/ISSUE_TEMPLATE/security.md
|
||||
Description: Issue template for security vulnerability reports
|
||||
Project: .github-private
|
||||
Author: Moko Consulting Tech
|
||||
Version: 03.02.00
|
||||
|
||||
Revision History:
|
||||
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
|
||||
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
|
||||
- 2024: Initial creation
|
||||
-->
|
||||
|
||||
## ⚠️ 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**:
|
||||
<!-- Low, Medium, or informational only -->
|
||||
|
||||
## Description
|
||||
<!-- Describe the security concern or improvement suggestion -->
|
||||
|
||||
## Affected Components
|
||||
<!-- List the affected files, features, or components -->
|
||||
|
||||
## Suggested Mitigation
|
||||
<!-- Describe how this could be addressed -->
|
||||
|
||||
## 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
|
||||
<!-- Add any other context about the security concern -->
|
||||
|
||||
## Checklist
|
||||
- [ ] This is NOT a critical vulnerability requiring private disclosure
|
||||
- [ ] I have reviewed the SECURITY.md policy
|
||||
- [ ] I have provided sufficient detail for evaluation
|
||||
@@ -1,309 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: MokoStandards.Templates.GitHub
|
||||
INGROUP: MokoStandards.Templates
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||
PATH: /templates/github/copilot-instructions.md.template
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Standard GitHub Copilot custom instructions template for Moko Consulting governed repositories
|
||||
NOTE: Synced to .github/copilot-instructions.md in all governed repositories via bulk sync.
|
||||
Tokens replaced at sync time: MokoStandards-Template-Generic, https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic, PHP, Generic project
|
||||
-->
|
||||
|
||||
> [!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/<repo-name>` |
|
||||
> | `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
|
||||
<?php
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: 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
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: MokoStandards-Template-Generic.Documentation
|
||||
INGROUP: MokoStandards-Template-Generic
|
||||
REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
|
||||
PATH: /docs/file.md
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: One-line description
|
||||
-->
|
||||
```
|
||||
|
||||
**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
|
||||
<?php
|
||||
/* … file header … */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use MokoStandards\Enterprise\CliFramework;
|
||||
|
||||
class MyScript extends CliFramework
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->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: `<type>(<scope>): <subject>` — 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/<workflow-name>.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 |
|
||||
@@ -1,126 +0,0 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License (./LICENSE).
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP:
|
||||
INGROUP: Project.Infrastructure
|
||||
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
|
||||
VERSION: 00.00.01
|
||||
PATH: ./.github/copilot/README.md
|
||||
BRIEF: GitHub Copilot firewall configuration documentation
|
||||
-->
|
||||
|
||||
# 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 |
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# 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
|
||||
@@ -200,3 +200,5 @@ venv/
|
||||
*.coverage
|
||||
hypothesis/
|
||||
|
||||
profile.ps1
|
||||
.mcp.json
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
|
||||
+36
-2
@@ -1,4 +1,4 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# FILE INFORMATION
|
||||
DEFGROUP:
|
||||
INGROUP: Project.Documentation
|
||||
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-Template-Generic
|
||||
VERSION: 00.00.01
|
||||
PATH: ./CONTRIBUTING.md
|
||||
BRIEF: Contribution guidelines for the project
|
||||
@@ -125,3 +125,37 @@ If you have questions about contributing, feel free to open an issue or contact
|
||||
| Date | Version | Author | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| 2026-01-16 | 0.1.0 | Copilot | Initial contributing guidelines |
|
||||
|
||||
## Infrastructure Standards
|
||||
|
||||
All repositories in the MokoConsulting org follow these conventions:
|
||||
|
||||
### Release Tags
|
||||
|
||||
Every repo maintains 5 standard release channel tags:
|
||||
|
||||
- `development` - Active development builds
|
||||
- `alpha` - Early internal testing
|
||||
- `beta` - Broader testing / client UAT
|
||||
- `release-candidate` - Final QA before production
|
||||
- `stable` - Production release
|
||||
|
||||
### Branch Protection
|
||||
|
||||
- `main` is protected; only `jmiller` can push directly
|
||||
- All other contributors must use pull requests
|
||||
- PRs are automatically reviewed by Claude Code
|
||||
|
||||
### CI/CD
|
||||
|
||||
- Gitea Actions runs all CI workflows
|
||||
- GitHub Actions are disabled on mirrored repos
|
||||
- Workflows live in both `.github/workflows/` and `.gitea/workflows/`
|
||||
|
||||
### Update Servers (Joomla)
|
||||
|
||||
In manifest `<updateservers>`, Gitea must be priority 1, GitHub priority 2.
|
||||
|
||||
### Secrets
|
||||
|
||||
All repos have `GA_TOKEN` and `GH_TOKEN` as Actions secrets for API access.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
@@ -11,102 +11,194 @@
|
||||
You should have received a copy of the GNU General Public License (./LICENSE).
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP:
|
||||
INGROUP: Project.Documentation
|
||||
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
|
||||
VERSION: 00.00.01
|
||||
DEFGROUP: joomla-api-mcp.Documentation
|
||||
INGROUP: joomla-api-mcp
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
VERSION: 01.00.00
|
||||
PATH: ./README.md
|
||||
BRIEF: Generic coding project template according to MokoStandards
|
||||
BRIEF: MCP server for Joomla Web Services API operations
|
||||
-->
|
||||
|
||||
|
||||
[](https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic/releases/tag/v00)
|
||||
[](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/releases/tag/v00)
|
||||
[](LICENSE)
|
||||
[](https://www.php.net)
|
||||
[](https://nodejs.org)
|
||||
|
||||
# MokoStandards-Template-Generic
|
||||
# joomla-api-mcp
|
||||
|
||||
[](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 <hello@mokoconsulting.tech>
|
||||
Copyright © 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
## 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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
-
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: joomla-api-mcp.Documentation
|
||||
INGROUP: joomla-api-mcp
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
PATH: /docs/API.md
|
||||
VERSION: 00.00.01
|
||||
BRIEF: MCP tool reference documentation
|
||||
-->
|
||||
|
||||
# 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 |
|
||||
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# FILE INFORMATION
|
||||
DEFGROUP: joomla-api-mcp.Documentation
|
||||
INGROUP: joomla-api-mcp
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
PATH: /docs/ARCHITECTURE.md
|
||||
VERSION: 00.00.01
|
||||
BRIEF: Architecture overview and design decisions
|
||||
-->
|
||||
|
||||
# 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 |
|
||||
+95
-391
@@ -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 |
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
|
||||
+10
-33
@@ -1,8 +1,7 @@
|
||||
{
|
||||
// The tab key will cycle through the settings when first created
|
||||
// Sublime Text SFTP Plugin
|
||||
// Visit https://codexns.io/products/sftp_for_subime/settings for help
|
||||
|
||||
// sftp, ftp or ftps
|
||||
"type": "sftp",
|
||||
|
||||
"save_before_upload": true,
|
||||
@@ -14,43 +13,21 @@
|
||||
"confirm_sync": true,
|
||||
"confirm_overwrite_newer": false,
|
||||
|
||||
"host": "example.com",
|
||||
"user": "username",
|
||||
"host": "dev.mokoconsulting.tech",
|
||||
"user": "mokoconsulting_dev",
|
||||
"port": "22",
|
||||
|
||||
//Default
|
||||
//"port": "22",
|
||||
"ssh_key_file": "C:/Users/jmill/OneDrive/Documents/Keys/repos/joomla-api-mcp",
|
||||
//"password": "",
|
||||
|
||||
//Uncomment One:
|
||||
//"ssh_key_file": "absolute/path/to/key/file",
|
||||
//"password": "password",
|
||||
|
||||
"remote_path": "/example/path/",
|
||||
"remote_path": "/home/mokoconsulting_dev/",
|
||||
"ignore_regexes": [
|
||||
"\\.sublime-(project|workspace|settings)", "\\.libsass.json/",
|
||||
"sftp-config(-alt\\d?)?\\.json",
|
||||
"sftp-config(-alt\\d?)?\\.json", "sftp-config.json.template",
|
||||
"sftp-settings\\.json", "/venv/", "\\.svn/", "\\.hg/", "\\.git*",
|
||||
"\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "robots\\.txt",
|
||||
"desktop\\.ini", "configuration\\.php",
|
||||
"administrator/components/com_akeebabackup/backup", "\\.ffs*", "\\.md",
|
||||
"\\.zip", "\\.editorconfig"
|
||||
"desktop\\.ini", "\\.ffs*", "\\.editorconfig", "\\.md", "\\.zip", "docs/"
|
||||
],
|
||||
//"file_permissions": "664",
|
||||
//"dir_permissions": "775",
|
||||
|
||||
//"extra_list_connections": 0,
|
||||
|
||||
"connect_timeout": 30,
|
||||
//"keepalive": 120,
|
||||
//"ftp_passive_mode": true,
|
||||
//"ftp_obey_passive_host": false,
|
||||
//"ssh_key_file": "~/.ssh/id_rsa",
|
||||
//"sftp_sudo": false,
|
||||
//"sftp_debug": false,
|
||||
//"sftp_flags": ["-F", "/path/to/ssh_config"],
|
||||
|
||||
//"preserve_modification_times": false,
|
||||
//"remote_time_offset_in_hours": 0,
|
||||
//"remote_encoding": "utf-8",
|
||||
//"remote_locale": "C",
|
||||
//"allow_config_upload": false,
|
||||
"connect_timeout": 30
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@mokoconsulting/joomla-api-mcp",
|
||||
"version": "1.0.0",
|
||||
"description": "MCP server for Joomla Web Services API operations",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
"joomla-api-mcp": "dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"start": "node dist/index.js",
|
||||
"lint": "eslint src/",
|
||||
"setup": "node scripts/setup.mjs",
|
||||
"clean": "rm -rf dist/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.12.1",
|
||||
"zod": "^3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.3",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"license": "GPL-3.0-or-later",
|
||||
"author": "Moko Consulting <hello@mokoconsulting.tech>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp.git"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env node
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: joomla-api-mcp.Scripts
|
||||
* INGROUP: joomla-api-mcp
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
* PATH: /scripts/setup.mjs
|
||||
* VERSION: 00.00.01
|
||||
* BRIEF: Interactive setup — prompts for Joomla API connection details and writes config
|
||||
*/
|
||||
|
||||
import { createInterface } from 'node:readline/promises';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
const CONFIG_PATH = resolve(homedir(), '.joomla-api-mcp.json');
|
||||
|
||||
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
||||
|
||||
async function prompt(question, defaultValue) {
|
||||
const suffix = defaultValue ? ` [${defaultValue}]` : '';
|
||||
const answer = await rl.question(`${question}${suffix}: `);
|
||||
return answer.trim() || defaultValue || '';
|
||||
}
|
||||
|
||||
async function promptRequired(question) {
|
||||
let answer = '';
|
||||
while (!answer) {
|
||||
answer = (await rl.question(`${question}: `)).trim();
|
||||
if (!answer) {
|
||||
console.log(' This field is required.');
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('');
|
||||
console.log('=== joomla-api-mcp Setup ===');
|
||||
console.log('');
|
||||
console.log('This will create your configuration file at:');
|
||||
console.log(` ${CONFIG_PATH}`);
|
||||
console.log('');
|
||||
|
||||
// Check for existing config
|
||||
let existing = null;
|
||||
try {
|
||||
const raw = await readFile(CONFIG_PATH, 'utf-8');
|
||||
existing = JSON.parse(raw);
|
||||
console.log('Existing config found. You can add a new connection or overwrite.');
|
||||
console.log(` Current connections: ${Object.keys(existing.connections).join(', ')}`);
|
||||
console.log('');
|
||||
} catch {
|
||||
// No existing config
|
||||
}
|
||||
|
||||
const connectionName = await prompt('Connection name', 'production');
|
||||
const baseUrl = await promptRequired('Joomla site URL (e.g. https://www.example.com)');
|
||||
const apiToken = await promptRequired('Joomla API token');
|
||||
|
||||
const cleanUrl = baseUrl.replace(/\/+$/, '');
|
||||
|
||||
const insecureAnswer = await prompt('Skip TLS verification for self-signed certs? (y/N)', 'N');
|
||||
const insecure = insecureAnswer.toLowerCase() === 'y';
|
||||
|
||||
const connection = { baseUrl: cleanUrl, apiToken };
|
||||
if (insecure) {
|
||||
connection.insecure = true;
|
||||
}
|
||||
|
||||
let config;
|
||||
if (existing) {
|
||||
config = existing;
|
||||
config.connections[connectionName] = connection;
|
||||
const setDefault = await prompt(`Set "${connectionName}" as default connection? (y/N)`, 'N');
|
||||
if (setDefault.toLowerCase() === 'y') {
|
||||
config.defaultConnection = connectionName;
|
||||
}
|
||||
} else {
|
||||
config = {
|
||||
defaultConnection: connectionName,
|
||||
connections: {
|
||||
[connectionName]: connection,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
await writeFile(CONFIG_PATH, JSON.stringify(config, null, '\t') + '\n', 'utf-8');
|
||||
|
||||
console.log('');
|
||||
console.log(`Config written to ${CONFIG_PATH}`);
|
||||
console.log(` Connection "${connectionName}" configured for ${cleanUrl}`);
|
||||
console.log('');
|
||||
|
||||
const addAnother = await prompt('Add another connection? (y/N)', 'N');
|
||||
if (addAnother.toLowerCase() === 'y') {
|
||||
rl.close();
|
||||
// Re-run to add another
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
execFileSync('node', [new URL(import.meta.url).pathname], { stdio: 'inherit' });
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Setup complete. You can now use the MCP server.');
|
||||
console.log('');
|
||||
rl.close();
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(`Setup failed: ${err.message}`);
|
||||
rl.close();
|
||||
process.exit(1);
|
||||
});
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: joomla-api-mcp.Client
|
||||
* INGROUP: joomla-api-mcp
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
* PATH: /src/client.ts
|
||||
* VERSION: 01.00.00
|
||||
* BRIEF: HTTP client for Joomla Web Services API (v1)
|
||||
*/
|
||||
|
||||
import * as https from 'node:https';
|
||||
import * as http from 'node:http';
|
||||
import type { JoomlaConnection, ApiResponse } from './types.js';
|
||||
|
||||
const API_PREFIX = '/api/index.php/v1';
|
||||
const TIMEOUT_MS = 30_000;
|
||||
|
||||
export class JoomlaClient {
|
||||
private readonly base_url: string;
|
||||
private readonly headers: Record<string, string>;
|
||||
private readonly insecure: boolean;
|
||||
|
||||
constructor(conn: JoomlaConnection) {
|
||||
this.base_url = conn.baseUrl.replace(/\/+$/, '') + API_PREFIX;
|
||||
this.headers = {
|
||||
'Authorization': `Bearer ${conn.apiToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/vnd.api+json',
|
||||
};
|
||||
this.insecure = conn.insecure ?? false;
|
||||
}
|
||||
|
||||
async get(endpoint: string, params?: Record<string, string>): Promise<ApiResponse> {
|
||||
const url = this.buildUrl(endpoint, params);
|
||||
return this.request(url, 'GET');
|
||||
}
|
||||
|
||||
async post(endpoint: string, body?: unknown): Promise<ApiResponse> {
|
||||
const url = this.buildUrl(endpoint);
|
||||
return this.request(url, 'POST', body);
|
||||
}
|
||||
|
||||
async patch(endpoint: string, body: unknown): Promise<ApiResponse> {
|
||||
const url = this.buildUrl(endpoint);
|
||||
return this.request(url, 'PATCH', body);
|
||||
}
|
||||
|
||||
async delete(endpoint: string): Promise<ApiResponse> {
|
||||
const url = this.buildUrl(endpoint);
|
||||
return this.request(url, 'DELETE');
|
||||
}
|
||||
|
||||
private buildUrl(endpoint: string, params?: Record<string, string>): string {
|
||||
const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
||||
const url = new URL(`${this.base_url}${path}`);
|
||||
if (params) {
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
url.searchParams.set(key, value);
|
||||
}
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
private tryParseJson(raw: string): unknown | null {
|
||||
// Try full string first
|
||||
try { return JSON.parse(raw); } catch { /* fall through */ }
|
||||
|
||||
// Joomla may append HTML after JSON — find the last } or ] and try parsing up to that point
|
||||
const trimmed = raw.trimStart();
|
||||
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null;
|
||||
|
||||
const closer = trimmed.startsWith('{') ? '}' : ']';
|
||||
let idx = raw.lastIndexOf(closer);
|
||||
while (idx > 0) {
|
||||
try {
|
||||
return JSON.parse(raw.substring(0, idx + 1));
|
||||
} catch {
|
||||
idx = raw.lastIndexOf(closer, idx - 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private request(url: string, method: string, body?: unknown): Promise<ApiResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const parsed = new URL(url);
|
||||
const is_https = parsed.protocol === 'https:';
|
||||
const transport = is_https ? https : http;
|
||||
|
||||
const options: https.RequestOptions = {
|
||||
hostname: parsed.hostname,
|
||||
port: parsed.port || (is_https ? 443 : 80),
|
||||
path: parsed.pathname + parsed.search,
|
||||
method,
|
||||
headers: { ...this.headers },
|
||||
timeout: TIMEOUT_MS,
|
||||
};
|
||||
|
||||
if (this.insecure && is_https) {
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
|
||||
const payload = body !== undefined ? JSON.stringify(body) : undefined;
|
||||
if (payload) {
|
||||
(options.headers as Record<string, string>)['Content-Length'] = Buffer.byteLength(payload).toString();
|
||||
}
|
||||
|
||||
const req = transport.request(options, (res) => {
|
||||
const chunks: Buffer[] = [];
|
||||
res.on('data', (chunk: Buffer) => chunks.push(chunk));
|
||||
res.on('end', () => {
|
||||
const raw = Buffer.concat(chunks).toString('utf-8');
|
||||
let data: unknown;
|
||||
|
||||
// Joomla API may return JSON with text/html content-type,
|
||||
// and may append HTML error fragments after valid JSON.
|
||||
// Try to parse as JSON, trimming trailing non-JSON content.
|
||||
data = this.tryParseJson(raw) ?? raw;
|
||||
|
||||
resolve({ status: res.statusCode ?? 0, data });
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (err) => reject(err));
|
||||
req.on('timeout', () => {
|
||||
req.destroy();
|
||||
reject(new Error('Request timed out'));
|
||||
});
|
||||
|
||||
if (payload) {
|
||||
req.write(payload);
|
||||
}
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: joomla-api-mcp.Config
|
||||
* INGROUP: joomla-api-mcp
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
* PATH: /src/config.ts
|
||||
* VERSION: 01.00.00
|
||||
* BRIEF: Configuration loader for Joomla API MCP connections
|
||||
*/
|
||||
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
import type { JoomlaConfig, JoomlaConnection } from './types.js';
|
||||
|
||||
const CONFIG_FILENAME = '.joomla-api-mcp.json';
|
||||
|
||||
export async function loadConfig(): Promise<JoomlaConfig> {
|
||||
const config_path = process.env.JOOMLA_API_MCP_CONFIG
|
||||
? resolve(process.env.JOOMLA_API_MCP_CONFIG)
|
||||
: resolve(homedir(), CONFIG_FILENAME);
|
||||
|
||||
try {
|
||||
const raw = await readFile(config_path, 'utf-8');
|
||||
const parsed = JSON.parse(raw) as Partial<JoomlaConfig>;
|
||||
|
||||
if (!parsed.connections || Object.keys(parsed.connections).length === 0) {
|
||||
throw new Error('No connections defined in config');
|
||||
}
|
||||
|
||||
return {
|
||||
connections: parsed.connections,
|
||||
defaultConnection: parsed.defaultConnection ?? Object.keys(parsed.connections)[0],
|
||||
};
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
throw new Error(
|
||||
`Failed to load config from ${config_path}: ${message}\n` +
|
||||
`Create ${config_path} — see config.example.json for format.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function getConnection(config: JoomlaConfig, name?: string): JoomlaConnection {
|
||||
const key = name ?? config.defaultConnection;
|
||||
const conn = config.connections[key];
|
||||
if (!conn) {
|
||||
throw new Error(
|
||||
`Connection "${key}" not found. Available: ${Object.keys(config.connections).join(', ')}`,
|
||||
);
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
# Docs Index: /templates/repos/generic/src
|
||||
|
||||
## Purpose
|
||||
|
||||
This index provides navigation to documentation within this folder.
|
||||
|
||||
## Metadata
|
||||
|
||||
- **Document Type:** index
|
||||
- **Auto-generated:** This file is automatically generated by rebuild_indexes.py
|
||||
|
||||
## Revision History
|
||||
|
||||
| Change | Notes | Author |
|
||||
| --- | --- | --- |
|
||||
| Automated update | Generated by documentation index automation | rebuild_indexes.py |
|
||||
+1232
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: joomla-api-mcp.Types
|
||||
* INGROUP: joomla-api-mcp
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
|
||||
* PATH: /src/types.ts
|
||||
* VERSION: 01.00.00
|
||||
* BRIEF: TypeScript type definitions for Joomla API MCP server
|
||||
*/
|
||||
|
||||
export interface JoomlaConnection {
|
||||
baseUrl: string;
|
||||
apiToken: string;
|
||||
/** Skip TLS certificate verification (self-signed certs) */
|
||||
insecure?: boolean;
|
||||
}
|
||||
|
||||
export interface JoomlaConfig {
|
||||
connections: Record<string, JoomlaConnection>;
|
||||
defaultConnection: string;
|
||||
}
|
||||
|
||||
export interface ApiResponse {
|
||||
status: number;
|
||||
data: unknown;
|
||||
errors?: Array<{ title: string; detail?: string }>;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user